Skip to content

cre-4799: Don2Don sharding failover - #23457

Open
mchain0 wants to merge 9 commits into
developfrom
cre-4799
Open

cre-4799: Don2Don sharding failover#23457
mchain0 wants to merge 9 commits into
developfrom
cre-4799

Conversation

@mchain0

@mchain0 mchain0 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

added:

  • ExecutionCompleted and ShardHeartbeat Don2Don protobuf messages with F+1 quorum-based senders/receivers in a new core/capabilities/remote/sharding/ package
  • wired the OnExecutionCompleted lifecycle hook into the engine's deferred execution block
  • and extended the launcher to open workflow-shard-to-workflow-shard Don2Don streams for cross-shard delivery
  • Implemented secondary "cache-only" mode behind a ShardingFailoverEnabled config flag that makes non-primary shards load assigned workflows and cache trigger events without executing
  • plus an AllShardsResolver interface so the registry loads workflows on all assigned shards
  • added a failover e2e topology TOML, a Test_CRE_V2_FailoverManualSwap system test

dep. smartcontractkit/chainlink-protos#450

cre-4799

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

CORA - Pending Reviewers

Codeowners Entry Overall Num Files Owners
* 💬 23 @smartcontractkit/foundations, @smartcontractkit/core
/core/capabilities/ 💬 6 @smartcontractkit/keystone, @smartcontractkit/capabilities-team
/core/services/workflows/ 💬 5 @smartcontractkit/keystone
/core/web/resolver/ 💬 3 @smartcontractkit/foundations, @smartcontractkit/core
/.github/** 💬 1 @smartcontractkit/devex-cicd, @smartcontractkit/devex-tooling, @smartcontractkit/core
/docs/CONFIG.md 💬 1 @smartcontractkit/foundations, @smartcontractkit/core, @smartcontractkit/devrel

Legend: ✅ Approved | ❌ Changes Requested | 💬 Commented | 🚫 Dismissed | ⏳ Pending | ❓ Unknown

For more details, see the full review summary.

@github-actions

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting develop

@github-actions

Copy link
Copy Markdown
Contributor

I see you updated files related to core. Please run make gocs in the root directory to add a changeset as well as in the text include at least one of the following tags:

  • #added For any new functionality added.
  • #breaking_change For any functionality that requires manual action for the node to boot.
  • #bugfix For bug fixes.
  • #changed For any change to the existing functionality.
  • #db_update For any feature that introduces updates to database schema.
  • #deprecation_notice For any upcoming deprecation functionality.
  • #internal For changesets that need to be excluded from the final changelog.
  • #nops For any feature that is NOP facing and needs to be in the official Release Notes for the release.
  • #removed For any functionality/config that is removed.
  • #updated For any functionality that is updated.
  • #wip For any change that is not ready yet and external communication about it should be held off till it is feature complete.

# When true, secondary shards load assigned workflows and cache trigger events without executing.
# The primary shard sends ExecutionCompleted notifications so the secondary can drain its cache.
# Requires ShardingEnabled=true.
ShardingFailoverEnabled = false # Default

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to cresettings as a feature flag? It makes sense to enable on all nodes at the same time anyway + it will be easier to manage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a good idea, I took a note and we can change this as a separate PR

MethodTriggerEvent = "TriggerEvent"
MethodExecute = "Execute"
MethodTriggerEventAck = "TriggerEventACK"
MethodExecutionCompleted = "ExecutionCompleted"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly to my comment on the proto - I'd name it "ExecutionStatusUpdate"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, I will refactor in next iteration over whole. let's make it work and then we can make it beautiful ;)

Comment thread core/capabilities/launcher.go Outdated
donB.AcceptsWorkflows && len(donA.CapabilityConfigurations) > 0 { // add DON pair if B is workflow and A is capability
if donA.AcceptsWorkflows && len(donB.CapabilityConfigurations) > 0 || // add DON pair if A is workflow and B is capability
donB.AcceptsWorkflows && len(donA.CapabilityConfigurations) > 0 || // add DON pair if B is workflow and A is capability
donA.AcceptsWorkflows && donB.AcceptsWorkflows { // shard-to-shard for ExecutionCompleted failover delivery

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ha! this turned out to be super easy :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it looks like that, but I remember don2don filtering so I'm a bit skeptical until properly tested

expiryDuration time.Duration
}

func NewExecutionCompletedReceiver(primary commoncap.DON, handler ExecutionCompletedHandler, lggr logger.Logger) *ExecutionCompletedReceiver {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are receiver and sender wired into d2d comms at all? If not, maybe move them to a separate PR with the wiring?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wiring is done here: #23487

@trunk-io

trunk-io Bot commented Aug 21, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@mchain0
mchain0 requested a review from pavel-raykov August 21, 2026 13:58
@mchain0
mchain0 requested a review from bolekk August 21, 2026 15:55
@mchain0
mchain0 marked this pull request as ready for review August 21, 2026 15:58
@mchain0
mchain0 requested review from a team as code owners August 21, 2026 15:58
@mchain0
mchain0 enabled auto-merge August 21, 2026 15:58
@cl-sonarqube-production

Copy link
Copy Markdown


primaryAssignmentTOML := `
static_default_assignment = [0,1]
hashed_default_assignment = false

@Tofel Tofel Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wen test for hashed assignment?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's ring activation as default, so it's already covered and tests exist


[per_org_assignment]
org_test_failover = [1,0]
`

@Tofel Tofel Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about adding a comment in the test explaining what this modified jobspec does? two settings were modified here, I think it would be useful to have some context about their effect (as the intent is clear: workflow swapping... but why for example we need to modify both values?)

workflowIDs[i] = workflowID
workflowToShardIndex[workflowID] = 1
}
testLogger.Info().Strs("workflowIDs", workflowIDs).Msg("Deployed fresh workflows for swap phase")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am missing explanatory comments here, e.g.

  • what is supposed to happen with the original workflows deployed to shard0?
  • why do we need to swap them with other ones?
  • why we don't wait for newly deployed workflows to execute before we propose a new job?

Looking at the test naively I would just expect to see original workflows executing on shard1 after the failover, but here something more complex is going on and I don't really understand what.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants