Skip to content

Commit 3fa2283

Browse files
author
Michael Schwarz
committed
Merge branch 'master' into production
2 parents 2658c22 + 196f659 commit 3fa2283

122 files changed

Lines changed: 8546 additions & 5861 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"hooks": {
3+
"PostToolUse": [
4+
{
5+
"matcher": "Task",
6+
"hooks": [
7+
{
8+
"type": "command",
9+
"command": "entire hooks claude-code post-task"
10+
}
11+
]
12+
},
13+
{
14+
"matcher": "TodoWrite",
15+
"hooks": [
16+
{
17+
"type": "command",
18+
"command": "entire hooks claude-code post-todo"
19+
}
20+
]
21+
}
22+
],
23+
"PreToolUse": [
24+
{
25+
"matcher": "Task",
26+
"hooks": [
27+
{
28+
"type": "command",
29+
"command": "entire hooks claude-code pre-task"
30+
}
31+
]
32+
}
33+
],
34+
"SessionEnd": [
35+
{
36+
"matcher": "",
37+
"hooks": [
38+
{
39+
"type": "command",
40+
"command": "entire hooks claude-code session-end"
41+
}
42+
]
43+
}
44+
],
45+
"SessionStart": [
46+
{
47+
"matcher": "",
48+
"hooks": [
49+
{
50+
"type": "command",
51+
"command": "entire hooks claude-code session-start"
52+
}
53+
]
54+
}
55+
],
56+
"Stop": [
57+
{
58+
"matcher": "",
59+
"hooks": [
60+
{
61+
"type": "command",
62+
"command": "entire hooks claude-code stop"
63+
}
64+
]
65+
}
66+
],
67+
"UserPromptSubmit": [
68+
{
69+
"matcher": "",
70+
"hooks": [
71+
{
72+
"type": "command",
73+
"command": "entire hooks claude-code user-prompt-submit"
74+
}
75+
]
76+
}
77+
]
78+
},
79+
"permissions": {
80+
"deny": [
81+
"Read(./.entire/metadata/**)"
82+
]
83+
}
84+
}

.entire/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
tmp/
2+
settings.local.json
3+
metadata/
4+
logs/

.entire/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"enabled": true,
3+
"telemetry": true
4+
}

.golangci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: "2"
2+
3+
run:
4+
timeout: 5m
5+
6+
formatters:
7+
enable:
8+
- gofumpt # gofumpt formatter
9+
10+
settings:
11+
gofumpt:
12+
module-path: github.com/ClusterCockpit/cc-backend
13+
14+
linters:
15+
enable:
16+
- staticcheck # staticcheck = true
17+
- unparam # unusedparams = true
18+
- nilnil # nilness = true (catches nil returns of nil interface values)
19+
- govet # base vet; nilness + unusedwrite via govet analyzers
20+
21+
settings:
22+
staticcheck:
23+
checks: ["ST1003"]
24+
25+
govet:
26+
enable:
27+
- nilness
28+
- unusedwrite
29+
30+
exclusions:
31+
paths:
32+
- .git
33+
- .vscode
34+
- .idea
35+
- node_modules
36+
- internal/graph/generated # gqlgen generated code
37+
- internal/api/docs\.go # swaggo generated code
38+
- _test\.go # test files excluded from all linters

.goreleaser.yaml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
version: 2
12
before:
23
hooks:
34
- go mod tidy
45
builds:
56
- env:
67
- CGO_ENABLED=1
8+
- CC=x86_64-linux-musl-gcc
79
goos:
810
- linux
911
goarch:
@@ -34,6 +36,19 @@ builds:
3436
main: ./tools/archive-manager
3537
tags:
3638
- static_build
39+
- env:
40+
- CGO_ENABLED=0
41+
goos:
42+
- linux
43+
goarch:
44+
- amd64
45+
goamd64:
46+
- v3
47+
id: "archive-migration"
48+
binary: archive-migration
49+
main: ./tools/archive-migration
50+
tags:
51+
- static_build
3752
- env:
3853
- CGO_ENABLED=0
3954
goos:
@@ -48,7 +63,7 @@ builds:
4863
tags:
4964
- static_build
5065
archives:
51-
- format: tar.gz
66+
- formats: tar.gz
5267
# this name template makes the OS and Arch compatible with the results of uname.
5368
name_template: >-
5469
{{ .ProjectName }}_
@@ -59,7 +74,7 @@ archives:
5974
checksum:
6075
name_template: "checksums.txt"
6176
snapshot:
62-
name_template: "{{ incpatch .Version }}-next"
77+
version_template: "{{ incpatch .Version }}-next"
6378
changelog:
6479
sort: asc
6580
filters:
@@ -87,7 +102,7 @@ changelog:
87102
release:
88103
draft: false
89104
footer: |
90-
Supports job archive version 2 and database version 8.
105+
Supports job archive version 3 and database version 11.
91106
Please check out the [Release Notes](https://github.com/ClusterCockpit/cc-backend/blob/master/ReleaseNotes.md) for further details on breaking changes.
92107
93108
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

CLAUDE.md

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,11 @@ applied automatically on startup. Version tracking in `version` table.
151151
## Configuration
152152

153153
- **config.json**: Main configuration (clusters, metric repositories, archive settings)
154-
- `main.apiSubjects`: NATS subject configuration (optional)
155-
- `subjectJobEvent`: Subject for job start/stop events (e.g., "cc.job.event")
156-
- `subjectNodeState`: Subject for node state updates (e.g., "cc.node.state")
154+
- `main.api-subjects`: NATS subject configuration (optional)
155+
- `subject-job-event`: Subject for job start/stop events (e.g., "cc.job.event")
156+
- `subject-node-state`: Subject for node state updates (e.g., "cc.node.state")
157+
- `job-concurrency`: Worker goroutines for job events (default: 8)
158+
- `node-concurrency`: Worker goroutines for node state events (default: 2)
157159
- `nats`: NATS client connection configuration (optional)
158160
- `address`: NATS server address (e.g., "nats://localhost:4222")
159161
- `username`: Authentication username (optional)
@@ -227,6 +229,7 @@ The backend supports a NATS-based API as an alternative to the REST API for job
227229
### Setup
228230

229231
1. Configure NATS client connection in `config.json`:
232+
230233
```json
231234
{
232235
"nats": {
@@ -238,37 +241,49 @@ The backend supports a NATS-based API as an alternative to the REST API for job
238241
```
239242

240243
2. Configure API subjects in `config.json` under `main`:
244+
241245
```json
242246
{
243247
"main": {
244-
"apiSubjects": {
245-
"subjectJobEvent": "cc.job.event",
246-
"subjectNodeState": "cc.node.state"
248+
"api-subjects": {
249+
"subject-job-event": "cc.job.event",
250+
"subject-node-state": "cc.node.state",
251+
"job-concurrency": 8,
252+
"node-concurrency": 2
247253
}
248254
}
249255
}
250256
```
251257

258+
- `subject-job-event` (required): NATS subject for job start/stop events
259+
- `subject-node-state` (required): NATS subject for node state updates
260+
- `job-concurrency` (optional, default: 8): Number of concurrent worker goroutines for job events
261+
- `node-concurrency` (optional, default: 2): Number of concurrent worker goroutines for node state events
262+
252263
### Message Format
253264

254265
Messages use **InfluxDB line protocol** format with the following structure:
255266

256267
#### Job Events
257268

258269
**Start Job:**
270+
259271
```
260272
job,function=start_job event="{\"jobId\":123,\"user\":\"alice\",\"cluster\":\"test\", ...}" 1234567890000000000
261273
```
262274

263275
**Stop Job:**
276+
264277
```
265278
job,function=stop_job event="{\"jobId\":123,\"cluster\":\"test\",\"startTime\":1234567890,\"stopTime\":1234571490,\"jobState\":\"completed\"}" 1234571490000000000
266279
```
267280

268281
**Tags:**
282+
269283
- `function`: Either `start_job` or `stop_job`
270284

271285
**Fields:**
286+
272287
- `event`: JSON payload containing job data (see REST API documentation for schema)
273288

274289
#### Node State Updates
@@ -292,15 +307,38 @@ job,function=stop_job event="{\"jobId\":123,\"cluster\":\"test\",\"startTime\":1
292307
### Implementation Notes
293308

294309
- NATS API mirrors REST API functionality but uses messaging
295-
- Job start/stop events are processed asynchronously
310+
- Job start/stop events are processed asynchronously via configurable worker pools
296311
- Duplicate job detection is handled (same as REST API)
297312
- All validation rules from REST API apply
313+
- Node state updates include health checks against the metric store (identical to REST handler): nodes are grouped by subcluster, metric configurations are fetched, and `HealthCheck()` is called per subcluster. Nodes default to `MonitoringStateFailed` if no health data is available.
298314
- Messages are logged; no responses are sent back to publishers
299315
- If NATS client is unavailable, API subscriptions are skipped (logged as warning)
300316

317+
## Development Guidelines
318+
319+
### Performance
320+
321+
This application processes large volumes of HPC monitoring data (metrics, job
322+
records, archives) at scale. All code changes must prioritize maximum throughput
323+
and minimal latency. Avoid unnecessary allocations, prefer streaming over
324+
buffering, and be mindful of lock contention. When in doubt, benchmark.
325+
326+
### Change Impact Analysis
327+
328+
For any significant change, you MUST:
329+
330+
1. **Check all call paths**: Trace every caller of modified functions to ensure
331+
correctness is preserved throughout the call chain.
332+
2. **Evaluate side effects**: Identify and verify all side effects — database
333+
writes, cache invalidations, channel sends, goroutine lifecycle changes, file
334+
I/O, and external API calls.
335+
3. **Consider concurrency implications**: This codebase uses goroutines and
336+
channels extensively. Verify that changes do not introduce races, deadlocks,
337+
or contention bottlenecks.
338+
301339
## Dependencies
302340

303-
- Go 1.24.0+ (check go.mod for exact version)
341+
- Go 1.25.0+ (check go.mod for exact version)
304342
- Node.js (for frontend builds)
305343
- SQLite 3 (only supported database)
306344
- Optional: NATS server for NATS API integration

Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
TARGET = ./cc-backend
22
FRONTEND = ./web/frontend
3-
VERSION = 1.5.0
3+
VERSION = 1.5.3
44
GIT_HASH := $(shell git rev-parse --short HEAD || echo 'development')
55
CURRENT_TIME = $(shell date +"%Y-%m-%d:T%H:%M:%S")
66
LD_FLAGS = '-s -X main.date=${CURRENT_TIME} -X main.version=${VERSION} -X main.commit=${GIT_HASH}'
@@ -36,7 +36,7 @@ SVELTE_SRC = $(wildcard $(FRONTEND)/src/*.svelte) \
3636
$(wildcard $(FRONTEND)/src/header/*.svelte) \
3737
$(wildcard $(FRONTEND)/src/job/*.svelte)
3838

39-
.PHONY: clean distclean test tags frontend swagger graphql $(TARGET)
39+
.PHONY: clean distclean fmt lint test tags frontend swagger graphql $(TARGET)
4040

4141
.NOTPARALLEL:
4242

@@ -75,6 +75,14 @@ test:
7575
@go vet ./...
7676
@go test ./...
7777

78+
fmt:
79+
$(info ===> FORMAT)
80+
@gofumpt -l -w .
81+
82+
lint:
83+
$(info ===> LINT)
84+
@golangci-lint run ./...
85+
7886
tags:
7987
$(info ===> TAGS)
8088
@ctags -R

0 commit comments

Comments
 (0)