JobScheduler and Connecting know to expect a job started from firefly - #384
Conversation
c00c9b1 to
58a1a4a
Compare
ffc0db1 to
3da66d9
Compare
codingLogan
left a comment
There was a problem hiding this comment.
I'm reviewing this, albeit slowly. The parts I'm needing to validate are
- Web Sockets behavior with the new changes
- OAuth behavior for existing members that aren't PENDING
|
I had my AI take a swing at protecting the websocket flows and the non-PENDING member flows. It has some feedback, pretty small changes requested. 1. WebSocket Flows
|
|
@Craiting Here's what Fable 5.1 had to say. This is more of an informational dump, not a list of everything we need to change. We can discuss this and see what if anything we'd like to implement. Side note My prompt: Fable 5.1 PR ReviewI've reviewed the full diff plus the surrounding code (Connecting.js, JobSchedule.js, the Connect reducer, usePollMember, pollers.js, and Net changes (branch ct/CT-2495-connecting-stall, 2 commits) Problem being fixed: After an OAuth redirect, Connecting mounts holding a stale pre-OAuth member (PENDING, is_being_aggregated: false, most_recent_job_guid: src/utilities/JobSchedule.js — onJobFinished
src/redux/reducers/Connect.js — initializeJobSchedule
src/views/connecting/Connecting.js
TestsNew ConnectingOAuthJobs-test.tsx (5 integration scenarios with a fake backend), plus unit tests for the schedule and reducer changes. ──────────────────────────────────────────────────────────────────────────────── Risks 🔴 1. Unbounded retry loop via activeJobAttempt (no cap)Connecting.js:339-343. Whenever jobComplete runs with a foreign/null job and the member is CONNECTED, the effect re-runs and calls runJob again. There's no
Recommendation: cap attempts (e.g., 2–3), and on exhaustion either surface setConnectingError or treat the schedule as done. 🔴 2. job.job_type null dereference at Connecting.js:305 const isForeignJob = job.job_type !== activeJob.typejob is job ?? polledResponse.job ?? null — it can be null (polled member with no most_recent_job_guid, or websocket transport before a members/updated 🟠 3. Websocket transport yields jobs without job_typeMemberUpdateTransport.ts:57-63 — in websocket mode polledResponse.job is { guid, async_account_data_ready } only. If loadMostRecentJob fails and we fall 🟠 4. onUpsertMember now fires on every Connecting mountConnecting.js:240: member !== currentMember is a reference check, and loadMemberByGuid always returns a new object, so this consumer callback fires on every 🟠 5. updateMember failures are now silentPreviously a failed updateMember left the promise rejected and the schedule uninitialized (a stall, but a visible one). Now it's swallowed and the job runs 🟡 6. Extra network round-trip on every Connecting mountThe unconditional loadMemberByGuid refresh adds latency to the non-OAuth happy path too. Probably fine, but it's a global change for an OAuth-specific 🟡 7. Second polling pass ignores non-aggregation terminal statesConnecting.js:311-317 filters only on is_being_aggregated === false. If the member flips to CHALLENGED/DENIED while still aggregating, we keep polling until 🟡 8. Location push removed from the use-case pathUPDATE_MEMBER_SUCCESS used to pushLocation(STEPS.CONNECTING). The new reducer test explicitly asserts location is unchanged. This looks like a bug fix ✅ Things that look right
Top priorities before merge: fix the job.job_type deref (#2), and add an attempt cap to the retry (#1). |
* docs: plan for replacing the Connecting job patches with a bounded reconcile loop * refactor: run the Connecting job schedule as a bounded reconcile loop Replace the isForeignJob / nested-poll / activeJobAttempt trio in Connecting with runJobSchedule$, a pure observable that treats the backend as the source of truth: observe whatever is running, reconcile it against the schedule, start the next job, repeat. 409s and Firefly's redirect job go through the same path. The loop is capped at jobs.length + 3 iterations and errors with JobScheduleExhaustedError, which Connecting throws to the host error boundary. Previously a perpetual 409 (or an unloadable job) re-ran runJob every poll interval forever. Integration tests added for: a foreign job followed by every scheduled job, early data release still applying when nothing else is scheduled, and bounded termination under a backend that always rejects the job. * docs: CT-2495 reconcile loop summary, risks and next steps * chore: drop planning docs from the repo * refactor: trim comments that restate the code in the job schedule loop
|
🎉 This PR is included in version 2.39.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Fixes an issue (CT-2495) where Connect Widget could become stuck indefinitely on the Connecting... screen following an OAuth redirect.
active jobs.
Playwright test suite passing:

I ran all the cypress tests locally too and they all passed except the Spanish one and I think that was caused by a different issue.