Skip to content

Sources/orchestration: validate ordered delta-chain continuity before advancing state #326

Description

@LouisDeconinck

Problem

Some bulk-data feeds consist of independent objects:

filing-123.pdf
filing-456.pdf
filing-789.pdf

Those can be processed independently.

Other feeds form an ordered delta chain where every predecessor is required.

For example:

full snapshot
    ↓
D20260901.zip
    ↓
D20260902.zip
    ↓
D20260903.zip

A national registry may define the current state as:

latest full snapshot
+ every subsequent delta in publication order

For such a source, discovering and successfully parsing D20260903.zip is not sufficient if D20260902.zip is missing or failed.

Applying later deltas across a gap can produce a dataset that is structurally valid and whose pipeline reports success, but whose state is incorrect.

Relationship to #324

#324 correctly handles:

Which new or changed remote objects exist and have not been successfully processed?

This issue asks a different question:

Is this sequence complete enough that the next object may safely be applied?

I would keep these separate.

Remote collection discovery should not need to assume that every collection has sequence semantics.

Proposed solution

Add an optional ordered-sequence / continuity contract that can operate on discovered objects or partitions.

Conceptually:

sequence:
  keyFrom: filename
  pattern: "D{date:YYYYMMDD}.KBO.zip"
  orderBy: date
  requireContinuity: true

or more generally:

sequence:
  valueColumn: publication_date
  cadence: day
  requireContinuity: true

The exact configuration shape is less important than the semantics.

Expected behavior

Given:

2026-09-01 succeeded
2026-09-02 missing
2026-09-03 discovered

Duckle should report something like:

sequence status: blocked
expected: 2026-09-02
next observed: 2026-09-03
reason: sequence_gap

and must not advance the authoritative sequence state past the missing item.

Failure semantics

A discovered delta should only advance the sequence when its associated processing succeeds.

For example:

D01 succeeds
    -> sequence position = D01

D02 parse/publish fails
    -> sequence remains D01

D03 exists
    -> visible as discovered
    -> blocked by D02

Retrying D02 successfully should then make D03 eligible.

This should compose with Duckle's durable item/slice state rather than create another job system.

Missing versus late

A gap may simply mean the publisher has not released the file yet.

Useful states could therefore include:

waiting
blocked
complete
gap

and an optional grace period could distinguish:

expected item not published yet

from:

sequence gap persisted beyond expected publication window

Freshness alerting from #304 can remain responsible for notifying operators.

Sequence identity

The sequence position should be based on an explicit deterministic key such as:

publication date
monotonic sequence number
version number

Do not infer order solely from mtime unless the user explicitly chooses that semantics.

Initial baseline

The initial state should be explicit.

Examples:

start from latest successful full snapshot
start from sequence 123456
start from date 2026-01-01

This lets a monthly/full snapshot reset the required delta chain.

Full snapshot reset

Some feeds periodically publish a new full snapshot.

It should be possible to model:

full snapshot F2 succeeds
    ↓
sequence baseline becomes F2
    ↓
only deltas after F2 are required

The older chain can remain in provenance without blocking the new generation.

Out-of-order arrival

Discovery and application order should be distinct.

For example:

D03 arrives
D02 arrives ten minutes later

Duckle may discover both immediately, but should process/apply them according to the configured sequence where continuity is required.

Provenance

A run applying a delta should record enough information to answer:

sequence key
previous accepted sequence key
source object/version
producer run
resulting sequence position

so the reconstructed state can be audited.

Scope

This is not a general stream-processing framework.

The first implementation can support deterministic ordered feeds with:

date cadence
integer sequence

and block on gaps.

That already covers many registry and incremental bulk-data feeds.

Acceptance criteria

  1. an ordered daily/integer delta feed can declare a continuity requirement;
  2. a later item cannot advance state while an earlier required item is missing or failed;
  3. out-of-order discovery does not cause out-of-order application;
  4. successfully retrying the missing item unblocks subsequent items;
  5. a new accepted full snapshot can reset the sequence baseline;
  6. sequence position and predecessor identity are recorded in provenance;
  7. continuity uses existing durable run/item/slice primitives rather than a separate executor.

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions