Skip to content

adapter: split dynamodb.go into cohesive files (no behavior change)#957

Open
bootjp wants to merge 4 commits into
mainfrom
refactor/split-adapter-dynamodb
Open

adapter: split dynamodb.go into cohesive files (no behavior change)#957
bootjp wants to merge 4 commits into
mainfrom
refactor/split-adapter-dynamodb

Conversation

@bootjp

@bootjp bootjp commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

Behavior-preserving refactor: split the 9,328-line adapter/dynamodb.go into cohesive same-package (package adapter) files. This is pure code movement — types/functions/methods/consts are relocated with no signature changes, no logic changes, no renames, and no comment rewrites (comments move with their code). The compiled package is semantically identical.

dynamodb.go shrinks from 9,328 → 553 lines and now holds only the server core/registration (struct, options, constructor, Run/Stop, HTTP handler/dispatch/health, body-size readers, request-metrics recorder). 526 top-level declarations were relocated into 12 new files; 49 stayed in dynamodb.go.

File map (old region → new file)

File Lines Region
dynamodb.go (kept) 553 Server core: DynamoDBServer struct/options/NewDynamoDBServer, Run/Stop, proxyToLeader, handle/dispatchByTarget/dispatchOrWriteUnsupported, health-check handlers, maxDynamoBodyReader, countingReadCloser/dynamoResponseRecorder, request-metrics recorder/observers, target consts + dynamoOperationTargets
dynamodb_schema.go 938 Table+schema management: Create/Delete/Describe/ListTables handlers + decoders, schema structs (createTable*, dynamoKeySchema, dynamoGlobalSecondaryIndex, dynamoTableSchema), *dynamoTableSchema key-derivation methods (primary/GSI/legacy key builders, primaryKeyValues), describeTableShape, loadTableSchema*/loadTableGenerationAt
dynamodb_item_read.go 189 GetItem read path: getItemInput, getItem, parseGetItemInput, resolveGetItemTarget, readItemAtKeyAt, readLogicalItemAt
dynamodb_item_write.go 921 Put/Update/Delete write paths + one-phase dedup: write plans, retryItemWriteWithGeneration*, prepare{Put,Update,Delete}ItemWrite, buildItemWriteRequestWithSource, return-attribute helpers
dynamodb_query_scan.go 2,281 Query/Scan: handlers + decoders, read iterators (tableReadIterator/gsiReadIterator/keyRangeKVIterator), readPageState, read-bounds resolution, projection, GSI parallel read workers, key-condition expression parsing/matching, scan/query exclusive-start-key & projection validators
dynamodb_transact.go 1,220 BatchWrite / TransactWrite / TransactGet: handlers, plan builders, retry/backoff, table-generation fence verification, cleanupCommittedKeys
dynamodb_lease.go 522 Lease pre-pass helpers (recently merged in #952): leaseReadKeyless, leaseCheckScan, leaseCheckQuery, leaseCheckTransactGetItems, multiShardReadLeasePlan, queryLeaseKey/queryLeasePrefix/gsiQueryLeasePlan, resolveTransactGetItemKeys, leaseReadGroupKeys, transactGetItemKey/transactGetItemKeyFromSchema
dynamodb_expression.go 1,640 Expression parsing/evaluation: update-expression sections (SET/REMOVE/ADD/DELETE), document-path traversal, condition-expression evaluation (function/comparison/IN/BETWEEN handlers), set arithmetic
dynamodb_attrvalue.go 530 Attribute-value helpers: key encoding (attributeValueAsKey*, numeric/ordered-int encoders, segment escaping), equality/sort comparisons, clone helpers, reverseItems
dynamodb_errors.go 78 Error mapping: dynamoAPIError, writeDynamoError*, writeDynamoJSON, dynamoErrIsTransient, newDynamoAPIError
dynamodb_keys.go 191 Storage key prefixes/segments: dynamoTableMetaKey/dynamoItemKey/dynamoGSIKey (+ legacy variants), encode/decodeDynamoSegment, scanAllByPrefix*, nextScanCursor, minInt
dynamodb_migration.go 308 Legacy table key migration: ensureLegacyTableMigration*, migrateLegacy*, finalizeLegacyTableMigration
dynamodb_locks.go 123 Lock striping + txn read-ts: lockItemUpdate/lockTableOperations, stripeIndex, dynamoItemUpdateLockKey, nextTxnReadTS/pinReadTS, globalLastCommitTSProvider

(Pre-existing split files dynamodb_types.go, dynamodb_storage_codec.go, dynamodb_admin.go, dynamodb_admin_items.go were not touched. Test files were not split.)

No behavior change

This PR changes only the physical location of declarations within package adapter. No declaration body, signature, name, or comment was altered. Per-file imports were recomputed by goimports (verified: no encoding/json substituted for the aliased json "github.com/goccy/go-json"; no other import-path changes).

Verification evidence

  • go build ./... → exit 0
  • go vet ./adapter/ → exit 0
  • gofmt -l adapter/ → empty (clean)
  • go test -race -count=1 -run 'TestDynamoDB' -timeout 900s ./adapter/ok ... 23.3s (cache defeated with -count=1)
  • golangci-lint --config=.golangci.yaml run ./adapter/0 issues
  • go doc -all ./adapter — identical between true origin/main baseline (captured via git stash) and this branch (byte-for-byte diff empty). Confirms the full exported + unexported API surface is unchanged.
  • Per-declaration byte equality — a go/printer-based dumper printed every top-level declaration (sorted by name) from the original dynamodb.go and from the union of the new files; diff is empty → all 575 declarations byte-identical after gofmt normalization.
  • git diff --stat: dynamodb.go -8,788 lines; new files +8,941 (delta = the 12 package+import headers and blank separators).

Five-lens self-review

All five are n/a — pure move (no logic touched). Evidence: go doc -all identical, per-declaration byte-identical, full DynamoDB test suite green under -race.

  1. Data loss — n/a. No Raft propose/apply, FSM, snapshot, Pebble-sync, or TTL/expiry code was modified, only relocated. go doc -all + per-decl diff confirm identical bodies.
  2. Concurrency / distributed failures — n/a. Lock striping (dynamodb_locks.go), lease pre-pass (dynamodb_lease.go), retry/backoff, and GSI worker code moved verbatim. go test -race green.
  3. Performance — n/a. No hot-path code changed; identical bodies → identical allocations/round-trips. Benchmarks unaffected.
  4. Data consistency — n/a. MVCC/OCC/HLC/lease/read-ts code (nextTxnReadTS/pinReadTS, lease checks, generation-fence verification) moved unchanged.
  5. Test coverage — n/a. No branches added/changed; existing co-located *_test.go files (package-internal) remain valid and pass. A pure relocation adds no new behavior to test.

bootjp added 4 commits June 12, 2026 15:44
… files (no behavior change)

Pure code movement within package adapter: schema+table management,
storage key prefix/segment encoding, attribute-value compare/clone/
key-encode helpers, and DynamoDB error mapping/transient classifier move
out of dynamodb.go into dedicated dynamodb_schema.go / dynamodb_keys.go /
dynamodb_attrvalue.go / dynamodb_errors.go. No declarations changed
(byte-identical, gofmt; imports recomputed per file via goimports).
…hesive files (no behavior change)

Pure code movement within package adapter: GetItem read path,
Put/Update/Delete write paths + one-phase dedup, Query/Scan + read
iterators + key-condition parsing, BatchWrite/TransactWrite/TransactGet,
and the lease pre-pass helpers (leaseCheckScan/leaseCheckQuery/
leaseCheckTransactGetItems, multiShardReadLeasePlan, queryLeaseKey,
leaseReadGroupKeys) move into dynamodb_item_read.go /
dynamodb_item_write.go / dynamodb_query_scan.go / dynamodb_transact.go /
dynamodb_lease.go. No declarations changed.
…iles (no behavior change)

Pure code movement within package adapter: update-expression parsing,
condition-expression evaluation, document-path traversal move into
dynamodb_expression.go; legacy table key migration into
dynamodb_migration.go; item/table lock striping + txn read-ts helpers
into dynamodb_locks.go. No declarations changed.
…hange)

dynamodb.go now holds only the server core/registration: DynamoDBServer
struct + options + constructor, Run/Stop, HTTP handler/dispatch/health,
body-size readers, and the request-metrics recorder. Imports trimmed to
what the core uses. No declarations changed.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@bootjp, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 33 minutes and 46 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c2de60e-f281-4a71-b8f3-b2edb4ada246

📥 Commits

Reviewing files that changed from the base of the PR and between 688ba8a and cc09b2d.

📒 Files selected for processing (13)
  • adapter/dynamodb.go
  • adapter/dynamodb_attrvalue.go
  • adapter/dynamodb_errors.go
  • adapter/dynamodb_expression.go
  • adapter/dynamodb_item_read.go
  • adapter/dynamodb_item_write.go
  • adapter/dynamodb_keys.go
  • adapter/dynamodb_lease.go
  • adapter/dynamodb_locks.go
  • adapter/dynamodb_migration.go
  • adapter/dynamodb_query_scan.go
  • adapter/dynamodb_schema.go
  • adapter/dynamodb_transact.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/split-adapter-dynamodb

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@bootjp

bootjp commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

@claude review

@claude

claude Bot commented Jun 12, 2026

Copy link
Copy Markdown

Claude finished @bootjp's task in 2m 35s —— View job


PR Review: adapter: split dynamodb.go into cohesive files

Tasks

  • Gather context and understand the PR
  • Examine the changed files
  • Review for correctness, imports, and conventions
  • Post final review

Summary

This is a well-executed behavior-preserving refactor. The split is logically organized, import hygiene is correct, and no duplicate declarations were introduced. CI is still running (Test + Jepsen in progress; Docker Image CI and Reviewdog both passed).


Findings

Minor: dynamodb_errors.go missing from PR description file map

The PR description's file map table lists 11 new files but dynamodb_errors.go (78 lines) is omitted. The file IS correctly created and contains the expected error helpers (dynamoAPIError, writeDynamoError, writeDynamoJSON, writeDynamoErrorFromErr, dynamoErrIsTransient, newDynamoAPIError) — it's just not documented in the table. The first commit's message does mention it, so this is a description-only gap. Worth adding a row for completeness.

Minor: Line count discrepancy in description

The PR description states dynamodb.go shrinks to 553 lines, but the actual post-split file is 540 lines. This appears to be a minor oversight (the description was likely written before the final commit cc09b2d).


Verification checks

Check Result
encoding/json accidentally used instead of json "github.com/goccy/go-json" None found — all files that decode/encode JSON use the correct goccy alias
Duplicate func declarations across split files None found
Duplicate type declarations across split files None found
package adapter header in all new files Correct
Constants in dynamodb.go still reference kv.*Prefix correctly CorrectdynamoTableMetaPrefix, dynamoItemPrefix, etc. still alias kv.*
snapshotTS (used in dynamodb_keys.go) defined in package Correct — lives in adapter/ts.go:17
Imports: dynamoErrIsTransient comment preserved with the function Correct — the detailed "lease pre-pass" comment moved intact to dynamodb_errors.go
CI: Docker Image CI ✅ passed
CI: Reviewdog (lint) ✅ passed
CI: Test suite ⏳ in progress
CI: Jepsen ⏳ in progress

Code organization quality

The concern-per-file split is clean and sensible:

  • dynamodb_errors.go — error types + response helpers (a natural unit)
  • dynamodb_locks.go — lock striping + read-ts pin (tight coupling: lockItemUpdate, nextTxnReadTS, pinReadTS all affect write-path isolation)
  • dynamodb_lease.go — lease pre-pass guards (correctly co-located with their lease timeout constant, which stayed in dynamodb.go)
  • dynamodb_migration.go — legacy key migration (self-contained lifecycle)
  • dynamodb_expression.go — expression parsing/evaluation (largest standalone concern)

No issues with the split itself. Approachable as a reader now.


Verdict

Looks good. The two items above (missing table row and line-count nit in the description) are documentation-only. The code changes are purely mechanical file splits with no logic alterations. Once the Test and Jepsen CI runs complete green, this is ready to merge.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces a comprehensive DynamoDB-compatible adapter layer for the elastickv store, implementing attribute value handling, expressions, item reads/writes, transactional operations, GSI support, and legacy table migrations. A critical compilation and synchronization issue was identified in the GSI read worker pool initialization where a non-existent Go method is called on sync.WaitGroup.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +1577 to +1581
for range workerCount {
wg.Go(func() {
d.gsiReadWorker(ctx, readTS, filter, jobs, results, cancel)
})
}

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.

critical

The sync.WaitGroup type from the standard library does not have a Go method. Using wg.Go will cause a compilation failure. Additionally, because wg.Add is never called, wg.Wait() would return immediately, leading to a race condition where the results channel is closed while workers are still running.

Update this to use the standard wg.Add(1) and go func() pattern with defer wg.Done() to ensure correct synchronization.

	for range workerCount {
		wg.Add(1)
		go func() {
			defer wg.Done()
			d.gsiReadWorker(ctx, readTS, filter, jobs, results, cancel)
		}()
	}

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