Job notifications¶
VeriLib shows background job notifications for uploads, reclones, and atomizations on repositories you own or can edit. They appear in two places:
| Surface | URL / location | Purpose |
|---|---|---|
| Header bell | Every signed-in page (top navigation) | Quick glance + dropdown list |
| Background jobs page | /jobs (auth required) |
Full table view with In progress, Recent, and Hidden sections |
The bell links to View all → /jobs.
Not real-time push
Notifications are polled, not WebSockets. The UI refetches about every 5 seconds while jobs are active and about 30 seconds when idle. Refresh the page if you suspect a stale row.
What is a notification?¶
A notification is one row of work on one repository — not a separate database job entity. The frontend asks the API for repos in relevant states, then derives a human-readable status from existing data:
| Source | What it tells the UI |
|---|---|
repos.status_id |
Whether the repo is still in-flight (initial, submitted, processing, …) or terminal (approved, rejected) |
joblogs → upload_response |
Clone/upload progress and errors from the upload processor |
joblogs → livelog |
Atomization progress streamed from the atomizer worker |
| RabbitMQ queue inspect (limited) | Queue depth / position when a repo has no atoms yet and no livelog has started |
Implementation: JobNotificationsService in verilib-frontend (public/app/Services/JobNotificationsService.php).
Scope — which repos appear¶
Notifications are built only for repositories where the signed-in user has edit access:
- repos you own (
repos.user_id), and - repos shared with you via
reposhareswith edit permission.
You will not see upload/atomize activity on repos you can only view.
What is excluded¶
These repos are not listed, even if status_id looks “active”:
initialrepos with no job activity — noupload_responseorlivelogrows (idle placeholders, e.g. repo never started processing).- Terminal repos older than 30 days — completed/failed jobs drop off the Recent list after the lookback window.
- Repos outside your edit scope.
Certification / validate-worker jobs are not part of this feature today — only the upload → atomize pipeline.
Notification kinds¶
Each item has a kind label in the UI:
| Kind | UI label | Meaning |
|---|---|---|
queue |
In queue | Repo is waiting in the atomization RabbitMQ queue (no atoms yet, no livelog). Message may include queue position, e.g. #2 in line — 3 total queued. |
upload |
Uploading | Clone/upload phase — reading upload_response joblogs, or repo status is submitted. |
atomize |
Atomizing | Atomizer is running — latest message from livelog (e.g. Building libraries: …). |
done |
Complete | Terminal success — repo reached approved status. Message includes atom count when available. |
error |
Failed | Terminal failure — repo rejected, or last log entry carries an error message. |
Active vs terminal phase¶
| Phase | When | Bell behavior |
|---|---|---|
active |
Repo still in-flight (initial, submitted, processing, …) |
Counts toward “in progress”; faster polling |
terminal |
Repo approved or rejected | Stays in Recent until you hide it or it ages out (30 days) |
Clicking a notification opens the repo edit page: /edit?id={repo_id}.
How /jobs is organized¶
The /jobs page uses the same stats-table layout as certificates and lists three sections:
| Section | Contents |
|---|---|
| In progress | Active-phase notifications |
| Recent | Terminal notifications from the last 30 days |
| Hidden | Items you dismissed with × (see below) |
Columns: Repo, Summary, Status (kind tag), Message, Updated, Open, Hide / Restore.
Hide, dismiss, and restore¶
Dismissal is client-side only (browser localStorage). Nothing is deleted on the server.
| Action | Effect |
|---|---|
| × Hide (bell or table) | Removes the item from the bell and from In progress / Recent. On /jobs it moves to Hidden. |
| Hidden → Restore | Puts the item back in the bell and the appropriate section. |
| Open / click row | Navigates to the repo. Does not hide the notification — use × for that. |
Storage keys (per browser):
| Key | Purpose |
|---|---|
verilib_notifications_dismissed |
Set of notification_id values the user hid |
verilib_notifications_hidden_active |
For stuck active jobs: maps repo_id → notification_id so the same in-progress job stays hidden until a new job starts on that repo |
A hidden in-progress job reappears automatically when atomization/upload restarts and the backend issues a new notification_id (derived from repo id, kind, and latest log id).
API¶
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET |
/v2/user/job-notifications |
Session (logged in) | Returns { items: [...], active_count: N } |
Each item shape (abbreviated):
{
"notification_id": "5224:atomize:99",
"repo_id": 5224,
"slug": "secure-messaging",
"summary": "Secure messaging protocols",
"kind": "atomize",
"phase": "active",
"repo_status": "processing",
"message": "Building libraries: SecureMessaging",
"queue_info": null,
"updated_at": "2026-08-11T12:59:05+00:00",
"href": "/edit?id=5224"
}
notification_id is stable for a given repo + kind + latest log row. When processing advances and log ids change, ids update — which is why hide-on-active uses the repo-level snapshot above.
Web route (PHP, not /v2):
| Route | Auth | View |
|---|---|---|
GET /jobs |
Yes | Mounts the React notifications bundle on #jobs-root |
End-to-end flow¶
sequenceDiagram
participant User
participant Bell as Header bell /jobs
participant API as GET /v2/user/job-notifications
participant DB as MySQL repos joblogs
participant MQ as RabbitMQ atomize queue
User->>Bell: Open site (signed in)
loop Every 5s active / 30s idle
Bell->>API: Poll
API->>DB: Repos user can edit in-flight or terminal
API->>DB: upload_response + livelog per repo
API->>MQ: Queue inspect (cap 5 repos, no atoms yet)
API-->>Bell: items + active_count
end
User->>Bell: Hide ×
Bell->>Bell: localStorage dismissed / hidden_active
Related¶
- Frontend — PHP app and React bundles
- API spec — full
/v2inventory - Queue workers — upload and atomize consumers
- Atomizer — produces
livelogevents - Error codes — upload/atomize failure messages surfaced in
message