Skip to content

Fix review findings: integration/s3-sink (hy-dq5u) - #15

Merged
philcunliffe merged 1 commit into
integration/s3-sinkfrom
polecat/hy-dq5u
May 22, 2026
Merged

Fix review findings: integration/s3-sink (hy-dq5u)#15
philcunliffe merged 1 commit into
integration/s3-sinkfrom
polecat/hy-dq5u

Conversation

@philcunliffe

Copy link
Copy Markdown
Contributor

Summary

Fix review findings: integration/s3-sink

Implemented: s3 exportBatch terminal-failure path now returns retryPartitions=failures so driver outbox excludes already-uploaded partitions. Added test/plugins/s3-export-batch.test.js covering terminal, partial, and all-success paths.

Delivery

  • Issue: hy-dq5u
  • Branch: polecat/hy-dq5u
  • Integration target: integration/s3-sink
  • Eventual target: master

This PR is auto-merged into the integration branch once CI is green. Human
review for the full feature happens on the downstream PR
(integration/s3-sink -> master, PR #7), which is opened separately when the
feature is ready to ship.

Address the major review finding on PR #7: the s3 sink's `exportBatch`
terminal-failure return (`s3_credentials_missing`, `s3_access_denied`,
`s3_bucket_missing`, `s3_region_mismatch`, `s3_config_invalid`) omitted
`retryPartitions`. The sink driver at `src/core/sinks/driver.js:146`
falls back to the entire batch in that case, so a terminal error
landing on partition N caused the driver to outbox every partition in
the batch — including the N-1 partitions that had already been PUT to
S3. Subsequent retries would then double-export those objects.
Return `retryPartitions: failures` so the driver outboxes only the
partitions that actually failed. `failures` always has at least one
entry when `lastConfigFailure` is set because both are pushed in the
same catch block.
Adds `test/plugins/s3-export-batch.test.js` covering the terminal,
partial, and all-success exit paths, exercised through the real
`activate` registration path with an injected `__clientFactory`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@philcunliffe
philcunliffe merged commit 0b84510 into integration/s3-sinkMay 22, 2026
6 checks passed
philcunliffe added a commit that referenced this pull request May 22, 2026
* chore: seed integration/s3-sink for feature flow
* feat(s3): add @hypaware/s3 blob destination plugin (hy-myln) (#10)
Implements hy-s3-1: a bundled first-party plugin providing
hypaware.blob-store@1.0.0 and contributing the `s3` sink.
Plugin tree under hypaware-core/plugins-workspace/s3/:
- manifest declares network + read_env permissions and the s3 sink
- src/config.js: validates bucket/prefix/region/profile/storage_class/
server_side_encryption + endpoint_url/force_path_style; emits stable
s3_config_invalid errors
- src/keys.js: renders <prefix>/<dataset>/<segment>/<filename> matching
local-fs layout; normalizes prefix slashes; rejects keys outside the
configured prefix
- src/client.js: AWS SDK v3 wiring with injectable client factory and
a credential_source_kind detector that never leaks secret material
- src/errors.js: AWS SDK error -> stable error_kind mapping
(s3_credentials_missing, s3_access_denied, s3_bucket_missing,
s3_region_mismatch, s3_throttled, s3_put_failed, encoder_failed)
- src/index.js: sink composes ctx.query schema + ctx.storage rows + the
paired encoder; emits s3.client.init / s3.put_object /
s3.put_object.failed telemetry; closes terminal errors as
status=failed and surfaces transient failures as status=partial
Bundled wiring + dependencies:
- @hypaware/s3 added to V1_BUNDLED_PLUGIN_ALLOWLIST
- @aws-sdk/client-s3 + @aws-sdk/credential-provider-ini added to root
dependencies; npm pack --dry-run ships the new plugin tree
Tests (test/plugins/s3-*.test.js):
- s3-keys: key composition, prefix normalization, path-separator
stripping, within-prefix guard
- s3-config: required/optional fields, storage_class allowlist,
endpoint_url URL parsing, S3-compatible (MinIO) shape
- s3-client: credential_source_kind precedence + redaction contract
- s3-errors: full AWS SDK error -> stable kind mapping table
Hermetic smoke (s3_sink_export_fixture):
- Activates real format-parquet + s3 plugin trees with a fake injected
S3 client; fires one driver tick; asserts PutObject bucket/key/body,
decodes the body back into Parquet rows, and verifies the
s3.client.init / s3.put_object / sink.encode_partition telemetry
carries the expected attributes with no credential-shaped substring
Smoke fix (cli_bundled_plugins_activated):
- The allowlist now has 8 entries; the smoke selects 6, so
plugins_skipped is 2 and both format-jsonl and s3 emit
plugin.skipped logs
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(s3): return retryPartitions on terminal failure (hy-dq5u) (#15)
Address the major review finding on PR #7: the s3 sink's `exportBatch`
terminal-failure return (`s3_credentials_missing`, `s3_access_denied`,
`s3_bucket_missing`, `s3_region_mismatch`, `s3_config_invalid`) omitted
`retryPartitions`. The sink driver at `src/core/sinks/driver.js:146`
falls back to the entire batch in that case, so a terminal error
landing on partition N caused the driver to outbox every partition in
the batch — including the N-1 partitions that had already been PUT to
S3. Subsequent retries would then double-export those objects.
Return `retryPartitions: failures` so the driver outboxes only the
partitions that actually failed. `failures` always has at least one
entry when `lastConfigFailure` is set because both are pushed in the
same catch block.
Adds `test/plugins/s3-export-batch.test.js` covering the terminal,
partial, and all-success exit paths, exercised through the real
`activate` registration path with an injected `__clientFactory`.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: feature-launch <feature-launch@gas.city>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@platypii
platypii deleted the polecat/hy-dq5u branch May 28, 2026 06:37
Sign up for freeto 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.

1 participant

@philcunliffe