Skip to content

use raft.TCPTransport#35

Merged
bootjp merged 3 commits into
mainfrom
feature/transaction
Dec 14, 2023
Merged

use raft.TCPTransport#35
bootjp merged 3 commits into
mainfrom
feature/transaction

Conversation

@bootjp
Copy link
Copy Markdown
Owner

@bootjp bootjp commented Dec 13, 2023

No description provided.

Comment thread kv/raft.go Outdated
Comment thread kv/raft.go Outdated
@bootjp bootjp merged commit caa0f6b into main Dec 14, 2023
@bootjp bootjp deleted the feature/transaction branch December 14, 2023 11:54
bootjp added a commit that referenced this pull request Jun 3, 2026
…ers (#912)

## Summary
- S3 (`encodeBucket`) and DDB (`encodeTable`) now check that the on-disk
subdirectory matches `EncodeSegment([]byte(name))` from `_bucket.json` /
`_schema.json` before emitting any records.
- Closes task #35 (the M4 + M5 follow-up the original session-summary
tracked).

## Background

The reverse encoders use two identifiers for the same logical entity:
- On-disk subdir: `s3/<bucketDir>/`, `dynamodb/<tableDir>/` — decoder
spells as `EncodeSegment([]byte(name))`.
- Embedded name in `_bucket.json` / `_schema.json` — encoder uses for
MVCC keys (`s3keys.BucketMetaKey(pub.Name)`, base64'd `tableName`).

Until now, both sides were trusted independently. A tampered or
hand-rebuilt dump that renamed the directory without touching the JSON
(or vice versa) would silently emit records keyed by the JSON name while
pulling object / item bytes from a mismatched filesystem path — a
name/dir consistency violation that splits a single restore artifact
across two identities.

## Fix

After the existing empty-name guard, both encoders verify
`EncodeSegment([]byte(name)) == <dir>`. Mismatch fails closed with the
existing per-adapter sentinel (`ErrS3EncodeInvalidBucket` /
`ErrDDBEncodeInvalidSchema`), and the error message names both the JSON
value and the encoded form so the operator can correct the dump.

## Caller audit (CLAUDE.md semantic-change rule)

- `encodeBucket` (S3): success path gains one new fail-closed check;
sole production caller is `S3RecordEncoder.Encode`.
- `encodeTable` (DDB): success path gains one new fail-closed check;
sole production caller is `DynamoDBEncoder.Encode`.
- Both checks reuse existing per-adapter sentinels, so
`runAdapterEncoders`' `errors.Mark(ErrEncodeAdapterData)` wrap still
routes failures through the CLI's exit-2 classification — no new
sentinel needed in `classifyEncodeError`.

## Self-review of code changes (5 lenses)

1. **Data loss** — Stricter validation; no commit/apply path touched. No
data-loss surface.
2. **Concurrency / distributed failures** — Encoder is single-process /
single-goroutine on the input tree. No new concurrency surface.
3. **Performance** — One extra `EncodeSegment` call and string compare
per bucket / per table. Negligible.
4. **Data consistency** — This IS the data-consistency improvement. The
check enforces the round-trip invariant `<dir> == EncodeSegment(name)`
for every published record.
5. **Test coverage** — Two new tests (one per adapter) pin the
rejection. Existing positive tests use `EncodeSegment` for the dir
spelling, so they remain green; existing rejection tests trip earlier
guards, also green.

## Test plan
- [x] `go test -race ./internal/backup/...
./cmd/elastickv-snapshot-encode/...`
- [x] `golangci-lint --config=.golangci.yaml run`
- [ ] Bot review cycle (claude / codex / CodeRabbit)
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.

1 participant