Skip to content

fix: Send checkpoints from resource hooks after their resources - #419

Merged
kodiakhq[bot] merged 10 commits into
mainfrom
fix/checkpoint-review-followups
Oct 20, 2026
Merged

kodiakhq[bot] merged 10 commits into
mainfrom
fix/checkpoint-review-followups

Conversation

@disq

@disq disq commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Checkpoints flushed while a resource is being resolved, for example from pre_resource_resolve or post_resource_resolve, now wait for that resource and its relations. Before, the scheduler ran a resource's hooks before putting the resource on the queue, so the CLI could save a cursor past rows it never received.

Also:

  • Flushing checkpoints outside their sync now raises SyncNotRunningError, a RuntimeError exported from cloudquery.sdk.stateclient.
  • Without checkpoints, setting a key to its current value no longer writes it to the backend again. With checkpoints it still sends a checkpoint, because later values of the key must follow the caller's resources.
  • New tests check that checkpoints follow grandchild relations.
  • The scheduler's thread pools keep their own max_workers instead of reading ThreadPoolExecutor's private copy, and a comment explains why the queue limit is a semaphore taken before submit().

@disq
disq changed the base branch from main to fix/scheduler-child-queue-size October 20, 2026 14:33
@disq
disq marked this pull request as ready for review October 20, 2026 14:33
@disq
disq requested a review from a team as a code owner October 20, 2026 14:33
@disq
disq requested review from erezrokah and mnorbury and removed request for a team October 20, 2026 14:33
Base automatically changed from fix/scheduler-child-queue-size to main October 20, 2026 14:41
disq added 2 commits October 20, 2026 15:44
…-followups

# Conflicts:
#	cloudquery/sdk/internal/checkpoint.py
#	cloudquery/sdk/stateclient/stateclient.py
#	tests/scheduler/checkpoints.py

@erezrokah erezrokah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please address the checkpoint-ordering regression described in the inline comment.

Comment on lines +94 to +98
if self.mem.get(key) == value:
# a pending change of the key summarizes this caller's resources too
if key in self.changes:
self.changes[key].add(scope)
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P1] Preserve checkpoint dependencies for unchanged cursor values

After flush() clears self.changes, this early return drops the caller’s scope entirely. For example, resolver A flushes cursor=1; resolver B yields a parent with an unfinished child, then sets and flushes the same cursor; resolver C subsequently flushes cursor=2. B’s flush now schedules no dependency, allowing checkpoint 2 onto the stream before B’s child. An interrupted sync can therefore persist a cursor past rows it never received. Please preserve resource dependencies for unchanged writes in checkpoint mode, even when suppressing redundant state writes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch, fixed in 2346dea. set_key now skips an unchanged value only when it writes to the backend directly. With checkpoints, an unchanged value still records the caller's scope, so B's flush sends a checkpoint that waits for B's child, and checkpoint 2 waits for it in turn. test_unchanged_values_order_later_checkpoints_after_the_callers_resources reproduces your A/B/C scenario and fails on the previous commit.

@disq disq added the automerge Add to automerge PRs once requirements are met label Oct 20, 2026
@kodiakhq
kodiakhq Bot merged commit fe8cc8f into main Oct 20, 2026
8 checks passed
@kodiakhq
kodiakhq Bot deleted the fix/checkpoint-review-followups branch October 20, 2026 15:11
kodiakhq Bot pushed a commit that referenced this pull request Oct 20, 2026
🤖 I have created a release *beep* *boop*
---


## [0.1.56](v0.1.55...v0.1.56) (2026-10-20)


### Bug Fixes

* Reject state changes from resolvers of an ended sync ([#417](#417)) ([bbd5b2e](bbd5b2e))
* Send checkpoints from resource hooks after their resources ([#419](#419)) ([fe8cc8f](fe8cc8f))
* Use the computed queue size for child resolver pools ([#416](#416)) ([0a4b408](0a4b408))

---
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
kodiakhq Bot pushed a commit to cloudquery/plugin-sdk that referenced this pull request Oct 20, 2026
#### Summary

With checkpoints, setting a key to the value it already had recorded nothing if the key had no pending change. A later value of the key could then reach the stream before the rows of the resolver that set the unchanged value, so the CLI could save a cursor past rows it never received. `SetKey` now records the caller's resources for unchanged values in checkpoint mode, and still skips them when it writes to the backend directly. The same issue was found and fixed in the Python SDK in cloudquery/plugin-sdk-python#419.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge Add to automerge PRs once requirements are met

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants