Job-status WebSocket events appear to be broadcast to every connected client
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
Direzione di ricerca
Start with backend/main.go, backend/controllers/websocket.go, backend/controllers/job_queue.go, and frontend/src/components/HomePage.tsx to trace connection registration and job-status handling. Reproduce the suggested two-session flow if the local Docker/OAuth environment can be started, then confirm the intended ownership model with maintainers. Done means the intended behavior is decided and verified, with a two-connection regression test if scoping is required.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
The frontend opens a job-status WebSocket at /ws?clientID=<uuid>, but the backend does not appear to read clientID (or any other user identifier) when registering the connection.
Authenticated sockets are stored in a process-wide clients map. JobStatusManager writes each JobStatus to every connection. JobStatus only contains a job name and a status string.
The home page treats incoming success events as belonging to the current user (toasts, and for most jobs a /tasks refetch).
The behavior is confirmed from the current source code, but has not yet been reproduced in two live authenticated sessions.
Current behavior (from source)
GET /wsis handled byAuthenticatedWebSocketHandler(backend/main.go).- After a valid session, the connection is stored as
clients[ws] = truewith no user/uuid key (backend/controllers/websocket.go). - The query string (
clientID) is not read in that handler. - Mutation handlers enqueue work on
GlobalJobQueue.AddJob/processJobsemitqueued,in-progress, andsuccessorfailureviaBroadcastJobStatus(backend/controllers/job_queue.go). JobStatusManagerranges overclientsandWriteJSONs the same payload to each socket.- Payload shape is only
{ "job": "...", "status": "..." }. HomePage.tsxconnects withws?clientID=${userInfo.uuid}and, onstatus === "success":- refetches tasks unless
job === "Edit Task"; - shows a success toast for
Add Task,Edit Task,Complete Task, andDelete Task.
- refetches tasks unless
If two users have /home open, the source implies User B would receive User A's job-status messages and could toast/refetch as if the job were B's.
Expected behavior
I am not assuming a specific design. Two reasonable options:
- Job-status events are only delivered to the user who queued the job (the unused
clientIDquery param suggests this may have been intended), or - Global broadcast is intentional (e.g. single-user / self-hosted assumption).
Please confirm which of these is intended.
Technical evidence
Backend
backend/main.go—mux.HandleFunc("/ws", controllers.AuthenticatedWebSocketHandler(store))backend/controllers/websocket.goJobStatus— fieldsJob,StatusonlyAuthenticatedWebSocketHandler— session check,Upgrade,clients[ws] = true; nor.URL.Query()/clientIDBroadcastJobStatus— send on the globalbroadcastchannelJobStatusManager—for client := range clients { client.WriteJSON(jobStatus) }
backend/controllers/job_queue.go—AddJob/processJobscallBroadcastJobStatuswithqueued/in-progress/success/failure- Example job name:
add_task.gousesName: "Add Task"
Frontend
frontend/src/components/HomePage.tsx—getWebSocketURL(\ws?clientID=${userInfo.uuid}`)andsocket.onmessage`frontend/src/components/utils/URLs.ts—getWebSocketURL(builds the URL; does not scope events)frontend/src/components/HomeComponents/Tasks/hooks.ts—fetchTaskwarriorTasks(GET/taskswith the current page's user headers)
A GET /tasks from that path calls FetchTasksFromTaskwarrior (including rm -rf /root/.task and task sync) on the backend. That is only relevant if B actually refetches because of A's event.
Suggested reproduction (not yet run here)
- Two browsers/profiles, two logged-in users, both on
/home. - DevTools → Network → WS on both; confirm URLs like
/ws?clientID=<A-uuid>and/ws?clientID=<B-uuid>. - User A adds a task.
- Compare WS frames on A and B.
- Check whether B shows
Task added successfully!and whether B issuesGET /taskswith B's session headers (do not log encryption secrets).
Predicted frames if fan-out matches the source:
{"job":"Add Task","status":"queued"}
{"job":"Add Task","status":"in-progress"}
{"job":"Add Task","status":"success"}
Runtime reproduction limitation
This was not reproduced with two live authenticated browser sessions. The local environment could not start the full Docker/OAuth stack (Docker engine not running, no backend/.env / frontend/.env).
Please treat the two-user UI outcome as unverified until someone captures those WS frames.
Questions for maintainers
- Should
/wsjob-status events be limited to the user who queued the job, or is broadcasting to every authenticated socket intentional? - If scoping is desired, should the unused
clientIDquery parameter be the key, or should the handler use the session UUID instead (so the client cannot pick another id)? - Should
JobStatusinclude a user/job owner field, or should routing stay entirely server-side?
Possible direction (not implemented)
If global broadcast is not intended:
- Associate each WebSocket with the session UUID at upgrade time (prefer session over the query string).
- Send
JobStatusonly to matching connections (and include the owner on theJobif needed). - Keep
HomePagetoasts/refetch only for events that belong to that user. - Add a test with two connections and different ids that a job for A is not written to B.
Happy to help with a two-session capture or a patch once the intended behavior is clear.
- Lingua principale
- TypeScript
- Stelle
- 37
- Fork
- 76
- Merge medio
- 3g 7h
- PR unite (30g)
- 2
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di CCExtractor/ccsync
-
GET /tasks is not serialized and Taskwarrior data isolation may race through shared /root/.taskAperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
CCExtractor/ccsync#471 · 3 commenti ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 45/100
CCExtractor/ccsync#440 · 3 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 25/100
CCExtractor/ccsync#433 · 2 commenti ·
-
enhancement frontend
Difficoltà 2/5 1-3 ore Idoneità per principianti 48/100
CCExtractor/ccsync#425 ·
-
backend complex enhancement
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
CCExtractor/ccsync#367 · 2 commenti ·
Tutte le issue di CCExtractor/ccsync
Issue simili
-
perf(core): getComments() runs the approved count and the comment list as two sequential queriesApertaarea/core bot:bug bot:working
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
emdash-cms/emdash#3905 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
lingdojo/kana-dojo#31728 · 1 commento · 5 reazioni ·
I maintainer di solito rispondono entro 1 giorno
-
selective-claw: freshTailTurns=0 keeps ALL turns verbatim and summarizes none (slice(-0) === slice(0))Forse già presa @zjncs l’ha presa oggi. Apertacomponent:tokenless
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
agentic-os-org/ANOLISA#6112 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug needs triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
rjsf-team/react-jsonschema-form#5439 ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno