{{ message }}
Repository navigation
[Project Sync] Add follower startup-sync trigger to Orca - #10089
Merged
daanvdk-mck merged 4 commits intoSep 24, 2026
Conversation
Contributor
Follower Contract HLD checklist item 10 (ML-12905): on boot (leader=orca), MLRun triggers Orca's leader-side reconciliation sweep for itself via a new SA-authenticated outbound call, then polls the resulting Trackable Action to a terminal state. Runs in a background thread with backoff-retry - never blocks FastAPI startup, since the sweep calls back into MLRun's own /follower/projects/* routes while it runs. Nothing consumes the resulting readiness signal yet (see the follow-up resource-creation-gate PR) - this PR is the trigger/poll machinery only.
daanvdk-mck
force-pushed
the
feature/ML-12905-startup-sync-resource-blocking
branch
from
September 9, 2026 08:21
03300a0 to
5ccd3e7
Compare
Contributor
|
Smoke Tests with the PR synced to |
Only the chief now triggers Orca's followers-sync sweep and polls it to completion - workers no longer each independently trigger their own, redundant sweep. Workers converge on the same readiness signal by asking the chief (new GET /api/v1/followers-sync-status, mirroring the existing clusterization-spec chief-proxy pattern) instead, caching the result once true since readiness is monotonic. This replaces the previous per-replica-independent design, which had two real problems: N redundant trigger calls to Orca per boot event, and inconsistent resource-creation gating across replicas depending on which one happened to finish its own trigger first.
Contributor
|
Smoke Tests with the PR synced to |
Confirmed live against orca's feature/ORIS-3532-trigger branch: the trigger response carries `correlationId` at the top level, not `opId`/`status.opId` as originally guessed, and the published action type is "follower-sync", not "sync-followers". Both were explicitly-flagged unverified guesses in the original code/comments - fixed now that a real implementation exists to check against. Renamed the local variable op_id -> correlation_id throughout for accuracy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
|
Smoke Tests with the PR synced to |
…ction Replace the hand-rolled threading.Thread + while/sleep/try-except retry loops with framework.utils.periodic.run_function_periodically - the same infra follower.Member already uses for _start_periodic_sync, and the pattern framework/service/__init__.py uses for the analogous worker-polls-chief case (_start_chief_clusterization_spec_sync_loop). This gets backoff and failure logging for free from the periodic wrapper instead of duplicating it, moves the trigger registration from initialize() (no running event loop there) to start() (already on the event loop, alongside _start_periodic_sync), and lets each function cancel its own periodic slot once it succeeds. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
|
Smoke Tests with the PR synced to |
Contributor
liranbg
approved these changes
Sep 16, 2026
daanvdk-mck
merged commit Sep 24, 2026
ffcc425
into
mlrun:feature/project-sync-follower
16 checks passed
daanvdk-mck
added a commit
that referenced
this pull request
Sep 24, 2026
…10103) ### 📝 Description Follower Contract HLD checklist item 9 (ML-12905): while this MLRun follower's project state isn't trustworthy, block creation of new logical resources (functions, API gateways) against it. Two conditions gate creation: the follower's own startup sync with the leader hasn't reached a terminal state yet (checklist item 10's readiness signal, `is_followers_sync_ready()`, built in #10089), or the specific project's own `status.state` is `creating`/`deleting`. --- ### 🛠️ Changes Made - `framework/utils/projects/follower.py`: new `Member.ensure_project_open_for_resource_creation()`. Raises `MLRunPreconditionFailedError` if `is_followers_sync_ready()` is false, or if the project's `status.state` is `creating`/`deleting`. A project with no recorded state yet (pre-dates the 2PC follower interface) is treated as online, not blocked. - `framework/utils/projects/member.py`: no-op default on the abstract base — MLRun-as-leader (CE) drives project state directly and synchronously, so there's no window where a project sits non-online while a caller races to create resources against it. - `services/api/api/endpoints/functions.py` / `nuclio.py`: wired the gate into `store_function`, `build_function`, `start_function`, `store_api_gateway` (added a `db_session` dependency), and `deploy_function`. --- ### ✅ Checklist - [ ] I updated the documentation (if applicable) - [x] I have tested the changes in this PR - [ ] I confirmed whether my changes are covered by system tests - [ ] If yes, I ran all relevant system tests and ensured they passed before submitting this PR - [ ] I updated existing system tests and/or added new ones if needed to cover my changes - [ ] If I introduced a deprecation: - [ ] I followed the [Deprecation Guidelines](./DEPRECATION.md) - [ ] I updated the relevant Jira ticket for documentation - [ ] Please run [Smoke-tests](https://github.com/mlrun/mlrun/actions/workflows/smoke-tests.yml) workflow, providing it the PR number as input (upon success, the workflow run will add label "Smoke tests: Pass" to the PR) --- ### 🧪 Testing - New unit tests: `test_follower_member.py` (+4: blocks-while-startup-sync-pending, blocks-non-online-project, allows-online-project, allows-unset-state), `test_leader_member.py` (+1: is-noop-for-leader). - Live end-to-end verification on a lab patched with this branch (at the time, stacked on #10089's pre-merge branch) against a real Orca implementation: confirmed the gate blocks resource creation while a project is mid-sync and clears once state settles. --- ### 🔗 References - Ticket link: https://ecliptos.atlassian.net/browse/ML-12905 - Design docs links: [Follower Contract HLD](https://ecliptos.atlassian.net/wiki/spaces/IRG/pages/654737417) (checklist item 9) · [Followers page](https://ecliptos.atlassian.net/wiki/spaces/IRG/pages/661979181) (MLRun §1) --- ### 🚨 Breaking Changes? - [ ] Yes (explain below) - [x] No --- ### 🔍️ Additional Notes - Base branch is `feature/project-sync-follower` (this epic's integration branch), not `development`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2 of 11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

📝 Description
Follower Contract HLD checklist item 10 (ML-12905): on boot (enterprise mode,
leader=orca), MLRun triggers Orca's leader-side reconciliation sweep for itself (POST /api/v1/projects/followers/sync, MLRun's own SA — not a user-identity relay) and polls the resulting Trackable Action to a terminal state. MLRun never reads a states list or computes its own diff — Orca pushes truth back onto MLRun's existing/follower/projects/*surface (ML-12901) while the sweep runs.Only the chief triggers the sweep. Workers converge on the same readiness signal by asking the chief (new
GET /api/v1/followers-sync-status, mirroring the existingclusterization-specchief-proxy pattern) instead of each independently triggering their own, redundant sweep against Orca.Scope note: this PR is the trigger/poll machinery only. It tracks readiness (a
threading.Event,is_followers_sync_ready()) but nothing consumes it for resource-creation blocking yet — the gate that reads this signal (checklist item 9, plus the blocking half of item 10) is a separate, follow-up PR, stacked on this branch, to be opened once this merges.Verified live end-to-end against a real implementation of orca's trigger endpoint (
feature/ORIS-3532-trigger) on a real lab: the full chain — chief trigger → real Orca sweep → real callbacks into MLRun's own/follower/projects/*endpoints → poll → chief readiness → worker-proxied readiness — all confirmed working. Two wire-format bugs (explicitly flagged as unverified guesses in the original code) were found and fixed this way: the trigger response field iscorrelationId(top-level), notopId/status.opId; the real action type is"follower-sync", not"sync-followers".Note: the ticket text describes startup-sync as a paginated
GET /api/v1/project-statespull-and-diff. That endpoint doesn't exist and contradicts the current, decided HLD (same class of stale-ticket-text issue ML-12903 hit) — this PR implements the HLD's actual, current design instead.🛠️ Changes Made
framework/utils/clients/iguazio/v4.py: newClient.trigger_followers_sync()(SA-authenticated POST + poll-to-terminal, mirrors the existing project-CUD trigger/poll pattern) and its supporting_send_self_authenticated_request/_wait_for_followers_sync/_verify_followers_sync_terminal.framework/utils/projects/follower.py: chief-only_start_periodic_followers_sync_trigger()and worker-only_start_periodic_followers_sync_wait_for_chief(), both registered fromstart()via the existingframework.utils.periodic.run_function_periodicallyinfra (the same mechanism_start_periodic_syncandframework/service/__init__.py's_start_chief_clusterization_spec_sync_loopalready use for analogous chief/worker background polling) instead of a hand-rolledthreading.Thread+ retry loop. Backoff-with-logging on failure comes for free from that infra; each function cancels its own periodic slot once it succeeds. Newis_followers_sync_ready()accessor.framework/utils/projects/member.py:is_followers_sync_ready()no-op-true default on the abstract base, so CE/leader mode (and any polymorphic caller that doesn't know which mode is running) is unaffected.framework/utils/clients/chief.py: newis_followers_sync_ready()— asks the chief via the new endpoint.services/api/api/endpoints/followers_sync_status.py(new):GET /followers-sync-status, chief answers locally, worker re-routes to chief. Registered inapi.py; added to theverify_api_stateallowlists indeps.pyalongsideclusterization-spec(same "clusterization purposes" category).✅ Checklist
🧪 Testing
test_iguazio_v4.py(+4: trigger success/SA-auth, missing-correlationId, poll-timeout, action-failed),test_follower_member.py(+8: non-orca-leader-ready-immediately, chief/workerinitialize()+start()integration, trigger sets-ready-and-cancels-on-success, trigger leaves-pending-on-failure, wait-for-chief sets-ready-and-cancels-when-ready, wait-for-chief stays-pending-when-not-ready,is_followers_sync_readyreflects the event),test_chief.py(+1:is_followers_sync_readyround-trip).feature/ORIS-3532-trigger: full trigger → sweep → callback → poll → readiness chain confirmed working, including the chief/worker readiness-consistency fix (both report identical readiness, worker via the new chief-proxy endpoint, not an independent check).🔗 References
🚨 Breaking Changes?
🔍️ Additional Notes
/api/v1/projects/followers/syncendpoint didn't exist onfeature/project-syncwhen this PR was originally opened; it now exists on orca'sfeature/ORIS-3532-triggerbranch and was used for the live verification above. Still not merged to orca's mainline.commit_delete_project's underlyingdelete_projectcall unconditionally blocks up to 300s waiting for Nuclio to confirm a project's deletion whenevernuclio_dashboard_urlis configured, regardless of leader mode. Inleader=orca, Nuclio is a separate peer follower Orca drives independently — MLRun's own follower-delete hook shouldn't wait on it. To be fixed in a separate session/PR.feature/ML-12905-resource-creation-gate; itsmlrun/mlrunPR will be opened once this one merges (GitHub won't let a cross-repo PR base on a fork-only branch).feature/project-sync-follower(this epic's integration branch), notdevelopment.🤖 Generated with Claude Code