Skip to content

refactor: rename disk package to storage#58

Merged
dkharms merged 1 commit into
mainfrom
38-storage-package
Aug 22, 2025
Merged

refactor: rename disk package to storage#58
dkharms merged 1 commit into
mainfrom
38-storage-package

Conversation

@dkharms
Copy link
Copy Markdown
Member

@dkharms dkharms commented Aug 1, 2025

Since we can have different storage backends (like local FS, S3, etc.), this change will make code easier to maintain in the future.

This is the first commit in the series of commits (#38)

Summary by CodeRabbit

  • Refactor

    • Replaced legacy disk-specific backend with a generic storage layer to support multiple storage backends (local/remote) and generic readers.
    • Public types and constructors updated to accept storage abstractions; added storage type indicator and read-only/upload interfaces.
  • Performance / Chores

    • Sealed-fraction cache now tracks versions to persist only when changed, reducing unnecessary disk writes.
  • Style / Documentation

    • Improved log messages and comments for clarity (e.g., "frac-cache").

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 1, 2025

📝 Walkthrough

Walkthrough

This change systematically replaces the internal disk package with storage across the codebase, updating imports, types, constructors, and method signatures. File handling is generalized from *os.File to io.ReaderAt, a new storage abstraction (storage/io.go) is added, and several interface assertions and minor cache persistence behaviors are introduced.

Changes

Cohort / File(s) Change Summary
Main commands
cmd/distribution/main.go, cmd/index_analyzer/main.go, cmd/unpacker/main.go
Replaced disk with storage imports; updated types (ReadLimiter, IndexReader) and constructor calls (IndexReader now receives reader name and io.ReaderAt).
Frac core & writers
frac/active.go, frac/active_index.go, frac/active_indexer.go, frac/active_sealer.go, frac/active_sealer_test.go, frac/active_writer.go, frac/compress.go, frac/doc_provider.go, frac/disk_blocks_writer.go, frac/info.go, frac/sealed.go, frac/sealed_index.go, frac/sealed_loader.go
Swapped diskstorage for DocBlock, DocsReader, IndexReader, ReadLimiter, BlocksWriter, etc.; updated struct fields, function signatures, constructors, and added interface assertions and a StorageType field.
Frac sealed submodules
frac/sealed/lids/loader.go, frac/sealed/seqids/loader.go, frac/sealed/seqids/provider.go, frac/sealed/token/block_loader.go, frac/sealed/token/table_loader.go
Replaced *disk.IndexReader with *storage.IndexReader; adjusted constructors and return types (e.g., IndexBlockHeader).
Frac manager & cache
fracmanager/fracmanager.go, fracmanager/fraction_provider.go, fracmanager/proxy_frac.go, fracmanager/sealed_frac_cache.go
Switched DocBlock and ReadLimiter types to storage.*; added proxyFrac interface assertion; introduced version-tracking for sealedFracCache persistence and log/message wording changes.
Proxy & storeapi
proxy/bulk/ingestor_test.go, proxy/search/streaming_doc.go, storeapi/grpc_fetch.go
Replaced disk.DocBlock usages with storage.DocBlock; updated packing/decompress calls and related return types.
Storage package files (rename/refactor)
storage/block_former.go, storage/blocks_stats.go, storage/blocks_writer.go, storage/codec.go, storage/doc_block.go, storage/doc_blocks_reader.go, storage/docs_reader.go, storage/index_block_header.go, storage/index_reader.go, storage/read_limiter.go
Changed package from diskstorage; refactored readers to use io.ReaderAt and added readerName to IndexReader; updated constructors and ReadLimiter.ReadAt to accept io.ReaderAt.
Storage new API
storage/io.go
New storage abstractions: Type constants, ImmutableFile interface, and Uploader interface.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Multiple cohesive, repetitive substitutions across many files plus medium-risk refactors (io.ReaderAt generalization, constructor signature changes, cache persistence logic) requiring checks for interface compatibility and caller updates.

Suggested reviewers

  • forshev
  • moflotas
  • eguguchkin

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 38-storage-package

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Aug 1, 2025

Codecov Report

❌ Patch coverage is 79.01235% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.19%. Comparing base (08fcb5e) to head (e61af42).

Files with missing lines Patch % Lines
fracmanager/sealed_frac_cache.go 30.00% 7 Missing ⚠️
cmd/distribution/main.go 0.00% 4 Missing ⚠️
cmd/index_analyzer/main.go 0.00% 2 Missing ⚠️
frac/disk_blocks_writer.go 83.33% 0 Missing and 2 partials ⚠️
cmd/unpacker/main.go 0.00% 1 Missing ⚠️
storage/index_reader.go 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #58      +/-   ##
==========================================
- Coverage   72.20%   72.19%   -0.01%     
==========================================
  Files         196      196              
  Lines       17359    17358       -1     
==========================================
- Hits        12534    12532       -2     
+ Misses       4135     4133       -2     
- Partials      690      693       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (2)
storage/doc_block.go (1)

105-113: Guard casts from RawLen to int

On 32-bit platforms, converting a 64-bit (or 32-bit) length to int can overflow silently (mod 2^32) and produce negative or truncated values, leading to panics or data corruption. We have two call sites:

  • storage/doc_block.go →
    b.Codec().decompressBlock(int(b.RawLen()), payload, dst)
  • storage/index_reader.go →
    header.Codec().decompressBlock(int(header.RawLen()), buf.B, dst)

Please add an explicit bounds check before the cast. For example:

--- a/storage/doc_block.go
+++ b/storage/doc_block.go
@@ func (b DocBlock) DecompressTo(dst []byte) ([]byte, error) {
-   return b.Codec().decompressBlock(int(b.RawLen()), payload, dst)
+   const maxInt = int(^uint(0) >> 1)
+   rawLen := b.RawLen()
+   if rawLen > uint64(maxInt) {
+       return nil, fmt.Errorf(
+           "raw length %d exceeds platform max int (%d)", rawLen, maxInt,
+       )
+   }
+   return b.Codec().decompressBlock(int(rawLen), payload, dst)
--- a/storage/index_reader.go
+++ b/storage/index_reader.go
@@ func (r *IndexReader) readBlock(...) {
-   dst, err = header.Codec().decompressBlock(int(header.RawLen()), buf.B, dst)
+   const maxInt = int(^uint(0) >> 1)
+   rawLen32 := header.RawLen()
+   if rawLen32 > uint32(maxInt) {
+       return nil, fmt.Errorf(
+           "raw length %d exceeds platform max int (%d)", rawLen32, maxInt,
+       )
+   }
+   dst, err = header.Codec().decompressBlock(int(rawLen32), buf.B, dst)

Optionally, you can refactor decompressBlock itself to accept uint64 (or uint32) and enforce these bounds internally.

storage/blocks_stats.go (1)

21-27: Divide-by-zero risk when Comp == 0

ratio := float64(s.Raw) / float64(s.Comp) panics if Comp is zero. A stats object coming from an empty or failed compression stage would trigger this.

 ratio := 0.0
-if s.Comp != 0 {
-    ratio = float64(s.Raw) / float64(s.Comp)
-}
+if s.Comp != 0 {
+    ratio = float64(s.Raw) / float64(s.Comp)
+}

At minimum, guard the calculation; consider logging a warning when Comp is zero so the anomaly is visible.

🧹 Nitpick comments (3)
proxy/bulk/ingestor_test.go (1)

423-433: Consider pre-allocating the destination buffer when decompressing blocks

storage.DocBlock(...).DecompressTo(nil) always allocates a new slice large enough to hold the decompressed data.
In large test suites this can lead to avoidable heap churn.
If you already know the exact uncompressed size (it is embedded in the block header), you can pass a pre-sized []byte and let DecompressTo reuse that memory.

-	binaryDocs, err := storage.DocBlock(c.docs).DecompressTo(nil)
+	dst := make([]byte, storage.DocBlock(c.docs).UncompressedLen()) // one allocation
+	binaryDocs, err := storage.DocBlock(c.docs).DecompressTo(dst)

Same applies to the binaryMetas path a few lines below.

frac/active_sealer_test.go (1)

70-72: Minor: keep index arithmetic in the same integer domain

storage.DocBlockHeaderLen and header.FullLen() are int; the slice bounds therefore operate in int space.
Keeping the indices consistently in int avoids hidden conversions:

-	header := storage.DocBlock(docBlocks[:storage.DocBlockHeaderLen])
-	docBlock := storage.DocBlock(docBlocks[:header.FullLen()])
+	header := storage.DocBlock(docBlocks[:storage.DocBlockHeaderLen])
+	docBlock := storage.DocBlock(docBlocks[:header.FullLen()])

(No behavioural change, just a reminder that both bounds are already int.)

frac/sealed/seqids/loader.go (1)

29-29: Optional: depend on an interface, not the concrete IndexReader

Loader.reader is currently a concrete *storage.IndexReader.
If you instead store an interface that exposes only ReadIndexBlock, unit-testing Loader becomes simpler (you can stub the reader) and you decouple from the storage package’s internal implementation.

type indexBlockReader interface {
    ReadIndexBlock(blockIdx uint32, dst []byte) ([]byte, int, error)
}

type Loader struct {
    reader indexBlockReader
    ...
}

A thin adapter around storage.IndexReader keeps production code unchanged.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2df2663 and 69bbb78.

📒 Files selected for processing (39)
  • cmd/distribution/main.go (2 hunks)
  • cmd/index_analyzer/main.go (4 hunks)
  • cmd/unpacker/main.go (2 hunks)
  • frac/active.go (5 hunks)
  • frac/active_index.go (3 hunks)
  • frac/active_indexer.go (3 hunks)
  • frac/active_sealer.go (4 hunks)
  • frac/active_sealer_test.go (3 hunks)
  • frac/active_writer.go (2 hunks)
  • frac/compress.go (3 hunks)
  • frac/disk_blocks_writer.go (8 hunks)
  • frac/doc_provider.go (2 hunks)
  • frac/info.go (3 hunks)
  • frac/sealed.go (8 hunks)
  • frac/sealed/lids/loader.go (2 hunks)
  • frac/sealed/seqids/loader.go (2 hunks)
  • frac/sealed/seqids/provider.go (2 hunks)
  • frac/sealed/token/block_loader.go (2 hunks)
  • frac/sealed/token/table_loader.go (2 hunks)
  • frac/sealed_index.go (3 hunks)
  • frac/sealed_loader.go (2 hunks)
  • fracmanager/fracmanager.go (2 hunks)
  • fracmanager/fraction_provider.go (3 hunks)
  • fracmanager/proxy_frac.go (1 hunks)
  • fracmanager/sealed_frac_cache.go (7 hunks)
  • proxy/bulk/ingestor_test.go (3 hunks)
  • proxy/search/streaming_doc.go (2 hunks)
  • storage/block_former.go (1 hunks)
  • storage/blocks_stats.go (1 hunks)
  • storage/blocks_writer.go (1 hunks)
  • storage/codec.go (1 hunks)
  • storage/doc_block.go (1 hunks)
  • storage/doc_blocks_reader.go (3 hunks)
  • storage/docs_reader.go (2 hunks)
  • storage/index_block_header.go (1 hunks)
  • storage/index_reader.go (5 hunks)
  • storage/io.go (1 hunks)
  • storage/read_limiter.go (2 hunks)
  • storeapi/grpc_fetch.go (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (22)
proxy/search/streaming_doc.go (1)
storage/doc_block.go (1)
  • DocBlock (23-23)
cmd/unpacker/main.go (2)
storage/doc_blocks_reader.go (1)
  • NewDocBlocksReader (14-19)
storage/read_limiter.go (1)
  • NewReadLimiter (14-19)
frac/active_sealer_test.go (1)
storage/doc_block.go (2)
  • DocBlock (23-23)
  • DocBlockHeaderLen (17-17)
fracmanager/fraction_provider.go (1)
storage/read_limiter.go (2)
  • ReadLimiter (9-12)
  • NewReadLimiter (14-19)
frac/sealed/seqids/loader.go (1)
storage/index_reader.go (1)
  • IndexReader (13-20)
frac/active_index.go (1)
storage/docs_reader.go (1)
  • DocsReader (11-14)
frac/sealed_index.go (1)
storage/docs_reader.go (1)
  • DocsReader (11-14)
fracmanager/proxy_frac.go (1)
frac/fraction.go (1)
  • Fraction (18-24)
frac/info.go (1)
storage/io.go (2)
  • Type (9-9)
  • TypeLocal (12-12)
frac/compress.go (1)
storage/doc_block.go (2)
  • DocBlock (23-23)
  • CompressDocBlock (79-88)
frac/sealed/seqids/provider.go (1)
storage/index_reader.go (1)
  • IndexReader (13-20)
storeapi/grpc_fetch.go (1)
storage/doc_block.go (3)
  • DocBlockHeaderLen (17-17)
  • PackDocBlock (90-99)
  • DocBlock (23-23)
fracmanager/sealed_frac_cache.go (2)
logger/logger.go (1)
  • Warn (70-72)
frac/info.go (1)
  • Info (22-45)
frac/sealed/token/block_loader.go (1)
storage/index_reader.go (1)
  • IndexReader (13-20)
frac/sealed.go (5)
frac/fraction.go (1)
  • Fraction (18-24)
storage/docs_reader.go (2)
  • DocsReader (11-14)
  • NewDocsReader (16-21)
frac/index_cache.go (1)
  • IndexCache (10-18)
storage/index_reader.go (2)
  • IndexReader (13-20)
  • NewIndexReader (22-32)
storage/read_limiter.go (1)
  • ReadLimiter (9-12)
frac/sealed/token/table_loader.go (4)
storage/index_reader.go (1)
  • IndexReader (13-20)
cache/cache.go (1)
  • Cache (60-68)
frac/sealed/token/table.go (1)
  • Table (17-17)
storage/index_block_header.go (1)
  • IndexBlockHeader (19-19)
frac/active_sealer.go (4)
frac/active_docs_positions.go (1)
  • DocsPositions (9-12)
storage/docs_reader.go (1)
  • DocsReader (11-14)
seq/seq.go (1)
  • ID (12-15)
storage/doc_block.go (1)
  • CompressDocBlock (79-88)
cmd/distribution/main.go (3)
storage/read_limiter.go (2)
  • ReadLimiter (9-12)
  • NewReadLimiter (14-19)
storage/index_reader.go (2)
  • IndexReader (13-20)
  • NewIndexReader (22-32)
cache/cache.go (1)
  • NewCache (70-86)
frac/sealed_loader.go (4)
storage/index_reader.go (1)
  • IndexReader (13-20)
frac/sealed/lids/loader.go (1)
  • Loader (16-21)
frac/sealed/seqids/loader.go (1)
  • Loader (28-35)
storage/index_block_header.go (1)
  • IndexBlockHeader (19-19)
frac/active_indexer.go (1)
storage/doc_block.go (1)
  • DocBlock (23-23)
storage/doc_blocks_reader.go (3)
storage/read_limiter.go (1)
  • ReadLimiter (9-12)
bytespool/bytespool.go (2)
  • AcquireLen (15-19)
  • Release (28-30)
storage/doc_block.go (1)
  • DocBlockHeaderLen (17-17)
storage/index_reader.go (4)
cache/cache.go (1)
  • Cache (60-68)
storage/read_limiter.go (1)
  • ReadLimiter (9-12)
storage/index_block_header.go (1)
  • IndexBlockHeaderSize (13-13)
bytespool/bytespool.go (2)
  • AcquireLen (15-19)
  • Release (28-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (79)
storage/index_block_header.go (1)

1-1: Package rename looks good

The move from diskstorage is clean in this file and requires no further action.

storage/codec.go (1)

1-1: Package rename acknowledged

No issues spotted; existing logic remains intact.

storage/doc_block.go (1)

1-1: Package rename is fine

Nothing else to flag on this line.

storage/block_former.go (1)

2-2: Package rename confirmed

No functional changes introduced here.

storage/blocks_writer.go (1)

1-1: Package rename confirmed

File compiles and behaviour is unchanged.

proxy/search/streaming_doc.go (1)

5-6: Package rename correctly applied

The switch to storage.DocBlock is consistent and keeps the logic unchanged.

Also applies to: 31-31

cmd/unpacker/main.go (1)

49-50: Nil metric handed to NewReadLimiter – verify nil-safety

storage.NewReadLimiter(1, nil) passes a typed-nil prometheus.Counter.
If ReadLimiter unconditionally calls metric.Inc() a runtime panic will occur.
Please confirm the implementation checks lim.metric != nil (or pass a real counter).

fracmanager/proxy_frac.go (1)

36-38: Compile-time interface assertion LGTM

The _ frac.Fraction = (*proxyFrac)(nil) line is a good safety net.

frac/active_writer.go (1)

38-40: Header update relies on meta size – double-check buffer length

storage.DocBlock(meta).SetExt1/SetExt2 mutate the slice in-place.
Ensure meta is at least the header size (16 bytes) before these calls; otherwise an out-of-bounds panic is possible.

fracmanager/fraction_provider.go (1)

24-33: LGTM – replacement with storage.ReadLimiter is straightforward

Constructor now delegates to storage.NewReadLimiter and the field type is updated accordingly. No functional impact observed.

frac/active_index.go (2)

59-60: LGTM – docsReader type update aligns with storage migration

Field type change to *storage.DocsReader propagates through the struct; read path implementations remain untouched. Good catch.


248-249: No further action – call site already uses the updated reader

ReadDocs now forwards to storage.DocsReader without modification.
Keep an eye on error-handling semantics if storage altered them, but nothing in this diff suggests a change.

frac/sealed_index.go (1)

23-23: LGTM: Clean package rename refactor

The import path update and corresponding type reference changes from disk.DocsReader to storage.DocsReader are consistent and mechanical. The DocsReader type maintains the same interface with reader and cache fields as shown in the relevant code snippets.

Also applies to: 70-70, 282-282

frac/doc_provider.go (1)

12-12: LGTM: Consistent package rename

The import path and return type signature updates are mechanically correct. The Provide() method logic remains unchanged, which is appropriate for this refactor.

Also applies to: 63-63

frac/compress.go (1)

10-10: LGTM: Complete and consistent package rename

All references to the disk package have been properly updated to storage:

  • Import path updated
  • Struct field types updated (docsBuf and metaBuf)
  • Function calls updated (CompressDocBlock)

The storage.CompressDocBlock function maintains the same signature and functionality as shown in the relevant code snippets.

Also applies to: 26-27, 53-53, 55-55

frac/info.go (1)

15-15: LGTM: Well-designed storage type addition

The addition of the StorageType field to track fraction storage location is well-implemented:

  • Proper import of the storage package
  • Clear documentation explaining the field's purpose
  • Sensible default initialization to storage.TypeLocal
  • Consistent with the PR objective to support multiple storage backends (local FS, S3, etc.)

Also applies to: 42-44, 60-60

fracmanager/fracmanager.go (1)

24-24: LGTM: Consistent method signature update

The import path and method parameter types are correctly updated from disk.DocBlock to storage.DocBlock. The method implementation remains unchanged, which is appropriate for this package rename refactor.

Also applies to: 316-316

fracmanager/sealed_frac_cache.go (5)

51-51: LGTM! Good documentation improvement.

The added comment clearly describes the purpose of the LoadFromDisk method.


55-55: LGTM! Consistent terminology standardization.

The changes standardize log messages to consistently use "frac-cache" instead of "frac cache", improving terminology consistency across the codebase.

Also applies to: 64-64, 70-70


76-76: LGTM! Documentation improvements following Go conventions.

The changes properly reference types and methods using square brackets following Go documentation conventions, and add missing punctuation for completeness.

Also applies to: 85-86, 96-96


121-121: LGTM! Consistent error message terminology.

The changes continue standardizing terminology to use "frac-cache" consistently in comments and error messages.

Also applies to: 125-125, 133-133


145-145: LGTM! Complete terminology standardization.

The changes complete the standardization of all log and error messages to consistently use "frac-cache" terminology throughout the file.

Also applies to: 157-157, 162-162, 166-166, 170-170, 174-174

frac/sealed/lids/loader.go (1)

5-5: LGTM! Clean package refactoring.

The changes correctly update the import from disk to storage and update the corresponding type references from *disk.IndexReader to *storage.IndexReader. This aligns with the PR objective to rename the disk package to storage for better multi-backend storage support.

Also applies to: 18-18, 23-23

frac/sealed/seqids/provider.go (1)

7-7: LGTM! Consistent package refactoring.

The changes properly update the import from disk to storage and the corresponding parameter type in NewProvider from *disk.IndexReader to *storage.IndexReader. This maintains consistency with the broader refactoring effort to standardize on the storage package.

Also applies to: 19-19

frac/active_indexer.go (1)

13-13: LGTM! Systematic package refactoring.

The changes systematically update references from the disk package to the storage package:

  • Import path updated appropriately
  • indexTask.Metas field type changed from disk.DocBlock to storage.DocBlock
  • Type conversion updated to use storage.DocBlock(metas).GetExt2()

The logic and functionality remain unchanged, maintaining API compatibility while adopting the new storage abstraction.

Also applies to: 26-26, 47-47

storeapi/grpc_fetch.go (1)

19-19: LGTM! Comprehensive package migration.

The changes thoroughly migrate from the disk package to the storage package:

  • Import updated from disk to storage
  • Constants and functions updated: storage.DocBlockHeaderLen and storage.PackDocBlock
  • Method return type updated from disk.DocBlock to storage.DocBlock

All changes maintain the same functionality while adopting the new storage abstraction, which aligns perfectly with the PR objective to support multiple storage backends.

Also applies to: 91-92, 170-170

storage/read_limiter.go (1)

1-30: LGTM! Clean abstraction improvement.

The refactor successfully generalizes the file reading interface from concrete *os.File to io.ReaderAt, making the code more flexible and testable. The receiver name change from r to rl improves readability.

frac/sealed_loader.go (3)

14-14: LGTM! Consistent package refactor.

The import update aligns with the broader refactoring from disk to storage package.


19-19: LGTM! Type reference correctly updated.

The reader field type is properly updated to use the new storage.IndexReader type.


66-66: LGTM! Return type correctly updated.

The return type change from disk.IndexBlockHeader to storage.IndexBlockHeader is consistent with the package refactor.

frac/sealed/token/block_loader.go (3)

13-13: LGTM! Import correctly updated.

The import change from disk to storage package is consistent with the refactor.


69-69: LGTM! Field type correctly updated.

The reader field type is properly updated to use *storage.IndexReader.


72-72: LGTM! Constructor parameter correctly updated.

The constructor parameter type matches the updated field type.

storage/docs_reader.go (3)

1-1: LGTM! Package name correctly updated.

The package rename from disk to storage aligns with the refactor objectives.


6-6: LGTM! Import correctly updated for abstraction.

The import change from os to io supports the generalization to io.ReaderAt interface.


16-20: LGTM! Clean API abstraction improvement.

The constructor signature improvements are excellent:

  • Parameter rename from reader to limiter is more descriptive
  • Generalization from *os.File to io.ReaderAt makes the code more flexible and testable
  • Constructor call properly uses the new abstracted parameters
frac/active.go (6)

23-23: LGTM! Import correctly updated.

The import change to storage package is consistent with the refactor.


27-29: LGTM! Formatting improvement.

The var declaration block improves code organization.


53-59: LGTM! Field types correctly updated.

All reader field types are properly updated to use the new storage package types.


78-78: LGTM! Constructor parameter type correctly updated.

The parameter type change to *storage.ReadLimiter is consistent with the refactor.


96-100: LGTM! Constructor calls properly updated.

The constructor calls correctly use the new storage package functions with io.ReaderAt abstraction. The docsFile parameter (which implements io.ReaderAt) is appropriately used.


179-180: LGTM! Type usage correctly updated.

The storage.DocBlock usage is consistent with the package migration and maintains the same functionality.

frac/sealed/token/table_loader.go (4)

11-11: LGTM - Import updated correctly for package refactor.

The import change from disk to storage package is consistent with the PR objective.


18-18: LGTM - Field type updated correctly for package refactor.

The reader field type change from disk.IndexReader to storage.IndexReader is consistent with the package rename.


24-24: LGTM - Constructor parameter type updated correctly.

The constructor parameter type change from *disk.IndexReader to *storage.IndexReader is consistent with the package refactor and field type change.


73-73: LGTM - Return type updated correctly for package refactor.

The return type change from disk.IndexBlockHeader to storage.IndexBlockHeader is consistent with the package rename and doesn't affect the method implementation.

storage/doc_blocks_reader.go (5)

1-1: LGTM - Package name updated correctly for refactor.

The package name change from disk to storage aligns with the PR objective.


4-4: LGTM - Import added for interface generalization.

The io import is necessary to support the io.ReaderAt interface used in the struct field.


11-11: LGTM - Field generalized to interface for better abstraction.

Changing the reader field from *os.File to io.ReaderAt is an excellent abstraction that enables support for multiple storage backends as mentioned in the PR objectives.


14-18: LGTM - Constructor updated with interface and bug fix.

The constructor changes improve the code in two ways:

  1. Parameter generalized from *os.File to io.ReaderAt for better abstraction
  2. Both limiter and reader fields are now correctly assigned (fixing a potential assignment bug mentioned in the AI summary)

25-25: LGTM - Method calls updated to use new reader field.

All ReadAt calls correctly updated to use r.reader instead of r.file, maintaining functionality while using the new interface-based approach.

Also applies to: 40-40, 54-54

frac/sealed.go (5)

19-19: LGTM - Import updated for package refactor.

The import change from disk to storage package is consistent with the PR objective.


23-25: LGTM - Compile-time interface compliance check added.

The interface compliance assertion var _ Fraction = (*Sealed)(nil) is good defensive programming that ensures Sealed continues to implement the Fraction interface.


39-39: LGTM - Struct field types updated for package refactor.

All field type changes (docsReader, indexReader, readLimiter) from disk.* to storage.* are consistent with the package rename and maintain the same functionality.

Also applies to: 43-43, 52-52


68-68: LGTM - Constructor parameters updated for package refactor.

The constructor parameter type changes from *disk.ReadLimiter to *storage.ReadLimiter are consistent with the field type changes and package refactor.

Also applies to: 141-141


107-107: LGTM - Constructor calls updated for new signatures.

The constructor calls are correctly updated:

  • storage.NewIndexReader calls now include the file name parameter as required by the new signature
  • storage.NewDocsReader calls use the updated package and maintain correct parameter order

Also applies to: 124-124, 153-153, 157-157

frac/active_sealer.go (3)

25-25: LGTM - Import updated for package refactor.

The import change from disk to storage package is consistent with the PR objective.


221-221: LGTM - Function parameters updated for package refactor.

The function parameter type changes from disk.DocsReader to storage.DocsReader are consistent with the package rename and don't affect the function logic.

Also applies to: 237-237


360-360: LGTM - Method call updated for package refactor.

The method call change from disk.CompressDocBlock to storage.CompressDocBlock is consistent with the package rename and maintains the same functionality.

storage/index_reader.go (5)

1-1: LGTM - Package name updated for refactor.

The package name change from disk to storage aligns with the PR objective of renaming the package.


16-17: LGTM - Struct fields improved for better abstraction.

The changes enhance the design:

  • reader field generalized from *os.File to io.ReaderAt enables support for multiple storage backends
  • readerName field addition provides useful identification for error messages and debugging

22-31: LGTM - Constructor updated for new struct design.

The constructor correctly:

  • Accepts the new readerName parameter for identification
  • Uses io.ReaderAt interface instead of concrete file type
  • Properly assigns all struct fields in the constructor body

46-46: LGTM - Error message improved with specific reader name.

Using r.readerName in the error message provides more specific and useful error information compared to a generic file reference.


57-57: LGTM - Method calls updated to use new reader field.

All ReadAt calls correctly updated from r.file to r.reader, maintaining functionality while using the new interface-based approach.

Also applies to: 69-69, 93-93, 100-100

storage/io.go (1)

1-30: Well-designed storage abstraction foundation.

This file establishes excellent foundational abstractions for the storage refactoring:

  1. Clear type definitions: The Type constants provide a clean way to distinguish between local and remote storage.
  2. Comprehensive file interface: ImmutableFile effectively combines the essential Go interfaces (io.Reader, io.ReaderAt, io.Seeker, io.Closer) with metadata access methods, creating a complete read-only file abstraction.
  3. Simple upload contract: The Uploader interface is focused and follows the single responsibility principle.

The design enables flexible storage implementations while maintaining a consistent API across the codebase.

cmd/distribution/main.go (4)

18-18: Import migration is consistent with the refactoring.

The update from disk to storage package aligns with the broader codebase refactoring to use generalized storage abstractions.


24-27: Variable type and constructor updates are correct.

The changes properly update both the variable type declaration and constructor call to use the new storage package equivalents while maintaining the same functionality.


44-50: Enhanced IndexReader constructor with reader identification.

The updated storage.NewIndexReader constructor now includes the file name (f.Name()) as an additional parameter, which improves debugging and logging capabilities by allowing the reader to be identified by name.


53-53: Function parameter type updated consistently.

The readBlock function parameter type is correctly updated to use storage.IndexReader instead of the previous disk.IndexReader.

cmd/index_analyzer/main.go (4)

11-18: Import updates are consistent with the storage refactoring.

The import changes properly migrate from the disk package to the storage package, maintaining the same functionality with the new storage abstractions.


33-33: ReadLimiter constructor updated correctly.

The constructor call is properly updated to use storage.NewReadLimiter instead of the previous disk.NewReadLimiter.


70-70: Function parameter type updated consistently.

The analyzeIndex function parameter type is correctly updated to use *storage.ReadLimiter instead of the previous disk package equivalent.


82-82: IndexReader constructor enhanced with reader identification.

The storage.NewIndexReader constructor call is properly updated to include the file name (f.Name()) parameter, which aligns with the new constructor signature and improves debugging capabilities.

frac/disk_blocks_writer.go (6)

11-11: Import migration is consistent with the refactoring.

The update from disk to storage package aligns with the broader codebase refactoring to use generalized storage abstractions.


17-18: Struct fields updated to use storage types.

The DiskBlocksWriter struct fields are correctly updated to use storage.BlocksWriter and storage.SealingStats instead of their disk package equivalents.


25-26: Constructor properly updated for storage package.

The constructor correctly initializes the writer and stats using storage.NewBlocksWriter and storage.SealingStats respectively, maintaining the same functionality with the new abstractions.


35-36: Method signature and implementation updated consistently.

The NewBlockFormer method return type and implementation are properly updated to use storage.BlockFormer and storage.NewBlockFormer.


47-53: Stats collection updated to use storage types.

The block statistics collection is correctly updated to append storage.BlockStats instead of the previous disk package equivalent, maintaining the same data structure and functionality.

Also applies to: 66-72


80-88: Flush options and compression settings migrated comprehensively.

All flush options, compression level settings, and related method calls are consistently updated to use their storage package equivalents:

  • storage.WithZstdCompressLevel
  • storage.WithExt
  • storage.FlushOption

The functionality remains identical while using the new storage abstractions.

Also applies to: 121-121, 174-174, 204-208

Comment thread frac/active_sealer_test.go
@dkharms dkharms changed the title refactor(all): rename disk package to storage Rename disk package to storage Aug 1, 2025
@ozontech ozontech deleted a comment from allcontributors Bot Aug 3, 2025
@ssnd ssnd added this to the v0.59.0 milestone Aug 13, 2025
@dkharms dkharms changed the title Rename disk package to storage refactor(all): rename disk package to storage Aug 14, 2025
@dkharms dkharms changed the title refactor(all): rename disk package to storage refactor: rename disk package to storage Aug 18, 2025
@ssnd ssnd modified the milestones: v0.59.0, v0.60.0 Aug 21, 2025
Since we can have different storage backends (like local FS, S3, etc.),
this change will make code easier to maintain in the future.
@dkharms dkharms force-pushed the 38-storage-package branch from 69bbb78 to e61af42 Compare August 22, 2025 11:40
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
fracmanager/sealed_frac_cache.go (1)

139-178: Fix temp-file handling: close/sync, ensure dir exists, and clean up on errors (prevents FD leaks and Windows rename failures).

Currently the temp file is never closed and not removed on errors. On Windows, renaming an open file can fail; on Unix you also want an fsync for durability. Add MkdirAll, defer cleanup, sync, and close before rename.

Apply this diff:

 func (fc *sealedFracCache) SaveCacheToDisk(version uint64, content []byte) error {
   fc.saveMu.Lock()
   defer fc.saveMu.Unlock()

   savedVersion := fc.savedVersion.Load()
   if version <= savedVersion {
     logger.Info("frac-cache already saved",
       zap.Uint64("version_to_save", version),
       zap.Uint64("saved_version", savedVersion))
     return nil
   }

   // we use unique temporary file
   //  * for atomic content changing
   //  * protect origin file from writing interruption
   //  * and to avoid race when writing (we can have several independent writers running at the same time, see tools/distribution/distribution.go)
+  if err := os.MkdirAll(fc.dataDir, 0o770); err != nil {
+    return fmt.Errorf("can't ensure frac-cache dir: %w", err)
+  }
-  tmp, err := os.CreateTemp(fc.dataDir, fc.fileName+".")
+  tmp, err := os.CreateTemp(fc.dataDir, fc.fileName+".")
   if err != nil {
     return fmt.Errorf("can't save frac-cache: %w", err)
   }
+  tmpName := tmp.Name()
+  // Best-effort cleanup if we exit early (noop after successful rename).
+  defer func() { _ = os.Remove(tmpName) }()
+  // Ensure the descriptor is closed even on errors.
+  defer func() { _ = tmp.Close() }()

   err = tmp.Chmod(defaultFilePermission)
   if err != nil {
     return fmt.Errorf("can't change frac-cache file permission: %w", err)
   }

   if _, err = tmp.Write(content); err != nil {
     return fmt.Errorf("can't save frac-cache: %w", err)
   }
+
+  if err = tmp.Sync(); err != nil {
+    return fmt.Errorf("can't flush frac-cache to disk: %w", err)
+  }
+  // Close before rename for Windows compatibility.
+  if err = tmp.Close(); err != nil {
+    return fmt.Errorf("can't close temp frac-cache file: %w", err)
+  }

-  if err = os.Rename(tmp.Name(), fc.fullPath); err != nil {
+  if err = os.Rename(tmpName, fc.fullPath); err != nil {
     return fmt.Errorf("can't rename tmp to actual frac-cache: %w", err)
   }

   fc.savedVersion.Store(version)
   logger.Info("frac-cache saved to disk",
     zap.String("filepath", fc.fullPath),
     zap.Uint64("version", version))
   return nil
 }

Optional (durability): fsync the parent dir after rename to survive metadata loss on crash. I can add that if desired.

cmd/unpacker/main.go (1)

24-29: Fix: defer on a possibly nil file handle can panic

defer inFile.Close() is scheduled before checking err. If os.OpenFile fails, inFile is nil and the deferred call will panic on return. Move the defer after the error check.

-	inFile, err := os.OpenFile(unpackFileName, os.O_RDONLY, 0o777)
-	defer func() { _ = inFile.Close() }()
-
-	if err != nil {
+	inFile, err := os.OpenFile(unpackFileName, os.O_RDONLY, 0o777)
+	if err != nil {
 		logger.Fatal("error opening file", zap.Error(err))
 	}
+	defer func() { _ = inFile.Close() }()
🧹 Nitpick comments (11)
proxy/bulk/ingestor_test.go (1)

423-425: Unify require style for consistency (use the r helper)

You’re using both r.NoError(err) and require.NoError(t, err) in the same test. Stick to the r helper for consistency.

-	binaryDocs, err := storage.DocBlock(c.docs).DecompressTo(nil)
-	require.NoError(t, err)
+	binaryDocs, err := storage.DocBlock(c.docs).DecompressTo(nil)
+	r.NoError(err)

-	binaryMetas, err := storage.DocBlock(c.metas).DecompressTo(nil)
-	require.NoError(t, err)
+	binaryMetas, err := storage.DocBlock(c.metas).DecompressTo(nil)
+	r.NoError(err)

Also applies to: 432-434

fracmanager/sealed_frac_cache.go (3)

51-74: Differentiate ENOENT vs read errors and avoid an immediate no-op rewrite after load.

Treat “file not found” as normal, but warn on other read errors. After successful load, align savedVersion with version to prevent an unnecessary write on the first SyncWithDisk.

 func (fc *sealedFracCache) LoadFromDisk(fileName string) {
   content, err := os.ReadFile(fileName)
   if err != nil {
-    logger.Info("frac-cache read error, empty cache will be created",
-      zap.Error(err),
-      zap.String("filename", fileName),
-    )
-    return
+    if os.IsNotExist(err) {
+      logger.Info("frac-cache not found, starting with empty cache",
+        zap.String("filename", fileName),
+      )
+      // Mark current state as saved to avoid immediate rewrite on first sync.
+      fc.savedVersion.Store(fc.version)
+      return
+    }
+    logger.Warn("frac-cache read error, empty cache will be created",
+      zap.Error(err),
+      zap.String("filename", fileName),
+    )
+    return
   }

   err = json.Unmarshal(content, &fc.fracCache)
   if err != nil {
     logger.Warn("can't unmarshal frac-cache, new frac-cache will be created later on",
       zap.Error(err),
     )
     return
   }

-  logger.Info("frac-cache loaded from disk",
+  // Loaded successfully; align savedVersion to avoid immediate rewrite.
+  fc.savedVersion.Store(fc.version)
+  logger.Info("frac-cache loaded from disk",
     zap.String("filename", fileName),
     zap.Int("cache_entries", len(fc.fracCache)),
   )
 }

Bonus: Adding a test that (1) loads an existing file and (2) asserts SyncWithDisk performs no write would recover some of the missing coverage flagged by Codecov for this file.


95-103: GetFracInfo returns an internal pointer—confirm immutability or return a copy.
If callers mutate the returned *frac.Info, they can corrupt the cache without bumping version. Either document the pointer as read-only or return a shallow copy to enforce immutability.


145-148: Consider downgrading “already saved” to a lower log level to reduce noise.
If a Debug/Trace level exists in your logger facade, prefer that for this high-frequency, non-actionable message.

cmd/unpacker/main.go (2)

24-25: Nit: tighten file modes

  • For os.O_RDONLY, the perm argument is ignored; pass 0 for clarity.
  • Avoid 0o777 on output files; 0o644 (or 0o666 to respect umask) is more appropriate.
-	inFile, err := os.OpenFile(unpackFileName, os.O_RDONLY, 0o777)
+	inFile, err := os.OpenFile(unpackFileName, os.O_RDONLY, 0)

-	outFile, err := os.OpenFile(outFileName, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o777)
+	outFile, err := os.OpenFile(outFileName, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o644)

Also applies to: 32-33


15-83: Improve testability of the CLI path

Codecov flags this file with 0% coverage. Consider extracting the unpack logic into a library function so it can be unit-tested without invoking main().

Example (outside this file):

// storage/unpack.go
func UnpackDocs(r io.ReaderAt, w io.Writer, log *zap.Logger) error { /* move the loop here */ }

Then call it from main() with inFile/outFile. I can draft this refactor and a basic happy-path test if helpful.

fracmanager/proxy_frac.go (2)

74-88: Avoid holding read lock while invoking underlying providers

DataProvider currently calls into active/sealed with useMu held. Not strictly wrong, but it lengthens lock hold time and could complicate future changes. Copy pointers, unlock, then call.

 func (f *proxyFrac) DataProvider(ctx context.Context) (frac.DataProvider, func()) {
-	f.useMu.RLock()
-	defer f.useMu.RUnlock()
-
-	if f.active != nil {
-		return f.active.DataProvider(ctx)
-	}
-
-	if f.sealed != nil {
-		metric.CountersTotal.WithLabelValues("use_sealed_from_active").Inc()
-		return f.sealed.DataProvider(ctx)
-	}
+	f.useMu.RLock()
+	active := f.active
+	sealed := f.sealed
+	f.useMu.RUnlock()
+
+	if active != nil {
+		return active.DataProvider(ctx)
+	}
+	if sealed != nil {
+		metric.CountersTotal.WithLabelValues("use_sealed_from_active").Inc()
+		return sealed.DataProvider(ctx)
+	}
 
 	return frac.EmptyDataProvider{}, func() {}
 }

103-109: Optional: capture name under lock to avoid races in logs

WaitWriteIdle reads f.active.BaseFileName without a lock. Low risk given call sites, but cheap to harden.

 func (f *proxyFrac) WaitWriteIdle() {
 	start := time.Now()
-	logger.Info("waiting fraction to stop write...", zap.String("name", f.active.BaseFileName))
+	name := ""
+	f.useMu.RLock()
+	if f.active != nil {
+		name = f.active.BaseFileName
+	}
+	f.useMu.RUnlock()
+	logger.Info("waiting fraction to stop write...", zap.String("name", name))
 	f.indexWg.Wait()
 	waitTime := util.DurationToUnit(time.Since(start), "s")
-	logger.Info("write is stopped", zap.String("name", f.active.BaseFileName), zap.Float64("time_wait_s", waitTime))
+	logger.Info("write is stopped", zap.String("name", name), zap.Float64("time_wait_s", waitTime))
 }
frac/sealed/seqids/loader.go (3)

39-46: Don’t cache empty blocks: move zero-length check into the loader closure.

Today an empty block may get cached and only then flagged as an error, which keeps a bad value in cache. Push the check inside the closure so empty results are never cached.

@@
-  data, err := l.cacheMIDs.GetWithError(index, func() ([]byte, int, error) {
-    data, _, err := l.reader.ReadIndexBlock(l.midBlockIndex(index), nil)
-    return data, cap(data), err
-  })
-  // check errors
-  if err == nil && len(data) == 0 {
-    err = errors.New("empty block")
-  }
+  data, err := l.cacheMIDs.GetWithError(index, func() ([]byte, int, error) {
+    data, _, err := l.reader.ReadIndexBlock(l.midBlockIndex(index), nil)
+    if err != nil {
+      return nil, 0, err
+    }
+    if len(data) == 0 {
+      return nil, 0, errors.New("empty block")
+    }
+    return data, cap(data), nil
+  })
@@
-  data, err := l.cacheRIDs.GetWithError(index, func() ([]byte, int, error) {
-    data, _, err := l.reader.ReadIndexBlock(l.ridBlockIndex(index), nil)
-    return data, cap(data), err
-  })
-  // check errors
-  if err == nil && len(data) == 0 {
-    err = errors.New("empty block")
-  }
+  data, err := l.cacheRIDs.GetWithError(index, func() ([]byte, int, error) {
+    data, _, err := l.reader.ReadIndexBlock(l.ridBlockIndex(index), nil)
+    if err != nil {
+      return nil, 0, err
+    }
+    if len(data) == 0 {
+      return nil, 0, errors.New("empty block")
+    }
+    return data, cap(data), nil
+  })

Also applies to: 60-67


29-29: Decouple Loader from the concrete storage.IndexReader via a tiny interface.

This improves testability and future backend swaps (e.g., S3) without touching call sites.

-type Loader struct {
-  reader      *storage.IndexReader
+type Loader struct {
+  reader      indexBlockReader
   table       *Table
   cacheMIDs   *cache.Cache[[]byte]
   cacheRIDs   *cache.Cache[[]byte]
   cacheParams *cache.Cache[BlockParams]
   fracVersion config.BinaryDataVersion
 }

Add this interface in the same file (outside the selected lines):

// indexBlockReader is the minimal dependency Loader needs.
type indexBlockReader interface {
  ReadIndexBlock(index uint32, buf []byte) ([]byte, int, error)
}

Note: Provider can keep passing *storage.IndexReader; it satisfies the interface.


106-107: Nit: storage-agnostic wording.

The comment still says “on disk”. Prefer backend-neutral phrasing.

-// blocks are stored as triplets on disk, (MID + RID + Pos), check docs/format-index-file.go
+// blocks are stored as triplets in the index storage (MID + RID + Pos), see docs/format-index-file.go
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 69bbb78 and e61af42.

📒 Files selected for processing (39)
  • cmd/distribution/main.go (2 hunks)
  • cmd/index_analyzer/main.go (4 hunks)
  • cmd/unpacker/main.go (2 hunks)
  • frac/active.go (4 hunks)
  • frac/active_index.go (3 hunks)
  • frac/active_indexer.go (3 hunks)
  • frac/active_sealer.go (4 hunks)
  • frac/active_sealer_test.go (3 hunks)
  • frac/active_writer.go (2 hunks)
  • frac/compress.go (3 hunks)
  • frac/disk_blocks_writer.go (8 hunks)
  • frac/doc_provider.go (2 hunks)
  • frac/info.go (3 hunks)
  • frac/sealed.go (8 hunks)
  • frac/sealed/lids/loader.go (2 hunks)
  • frac/sealed/seqids/loader.go (2 hunks)
  • frac/sealed/seqids/provider.go (2 hunks)
  • frac/sealed/token/block_loader.go (2 hunks)
  • frac/sealed/token/table_loader.go (2 hunks)
  • frac/sealed_index.go (3 hunks)
  • frac/sealed_loader.go (2 hunks)
  • fracmanager/fracmanager.go (2 hunks)
  • fracmanager/fraction_provider.go (3 hunks)
  • fracmanager/proxy_frac.go (1 hunks)
  • fracmanager/sealed_frac_cache.go (7 hunks)
  • proxy/bulk/ingestor_test.go (3 hunks)
  • proxy/search/streaming_doc.go (2 hunks)
  • storage/block_former.go (1 hunks)
  • storage/blocks_stats.go (1 hunks)
  • storage/blocks_writer.go (1 hunks)
  • storage/codec.go (1 hunks)
  • storage/doc_block.go (1 hunks)
  • storage/doc_blocks_reader.go (3 hunks)
  • storage/docs_reader.go (2 hunks)
  • storage/index_block_header.go (1 hunks)
  • storage/index_reader.go (5 hunks)
  • storage/io.go (1 hunks)
  • storage/read_limiter.go (2 hunks)
  • storeapi/grpc_fetch.go (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • storage/block_former.go
🚧 Files skipped from review as they are similar to previous changes (32)
  • fracmanager/fraction_provider.go
  • storage/blocks_stats.go
  • frac/sealed/token/block_loader.go
  • frac/doc_provider.go
  • storage/io.go
  • frac/active_sealer_test.go
  • storage/doc_blocks_reader.go
  • storage/doc_block.go
  • frac/active_index.go
  • storeapi/grpc_fetch.go
  • storage/blocks_writer.go
  • frac/sealed_index.go
  • fracmanager/fracmanager.go
  • proxy/search/streaming_doc.go
  • frac/info.go
  • storage/index_block_header.go
  • storage/read_limiter.go
  • cmd/index_analyzer/main.go
  • storage/index_reader.go
  • frac/sealed/token/table_loader.go
  • frac/compress.go
  • storage/codec.go
  • frac/active_sealer.go
  • frac/sealed.go
  • storage/docs_reader.go
  • cmd/distribution/main.go
  • frac/sealed_loader.go
  • frac/active_indexer.go
  • frac/active_writer.go
  • frac/active.go
  • frac/sealed/lids/loader.go
  • frac/disk_blocks_writer.go
🧰 Additional context used
🧬 Code graph analysis (6)
proxy/bulk/ingestor_test.go (1)
storage/doc_block.go (1)
  • DocBlock (23-23)
fracmanager/proxy_frac.go (1)
frac/fraction.go (1)
  • Fraction (18-24)
cmd/unpacker/main.go (2)
storage/doc_blocks_reader.go (1)
  • NewDocBlocksReader (14-19)
storage/read_limiter.go (1)
  • NewReadLimiter (14-19)
fracmanager/sealed_frac_cache.go (2)
logger/logger.go (1)
  • Warn (70-72)
frac/info.go (1)
  • Info (22-45)
frac/sealed/seqids/loader.go (1)
storage/index_reader.go (1)
  • IndexReader (13-20)
frac/sealed/seqids/provider.go (1)
storage/index_reader.go (1)
  • IndexReader (13-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test
🔇 Additional comments (8)
proxy/bulk/ingestor_test.go (1)

20-20: Import migration verified. The import of github.com/ozontech/seq-db/storage is correct, no legacy github.com/ozontech/seq-db/disk imports remain, and the DocBlock.DecompressTo(dst []byte) ([]byte, error) signature in storage/doc_block.go is intact.

fracmanager/sealed_frac_cache.go (3)

76-83: Version bump on add under write lock looks good.
The increment is protected by the same mutex as the map mutation—no data race here.


85-93: Delete path mirrors add path correctly.
Same locking and versioning approach; consistent and safe.


120-137: Sync gating by version is sound.
The snapshot + version compare avoids redundant writes; SaveCacheToDisk handles concurrent writers via version/savedVersion. Once SaveCacheToDisk fixes land, this path is solid.

cmd/unpacker/main.go (1)

49-49: ReadLimiter Nil Safety Verified

The storage/read_limiter.go constructor assigns the metric field from the counter argument, and the ReadLimiter’s Acquire method explicitly checks if rl.metric != nil before calling rl.metric.Add(...) (lines 26–28). Passing nil for the counter is therefore safe.

fracmanager/proxy_frac.go (1)

36-38: Nice: compile-time interface assertion

This guarantees proxyFrac continues to satisfy frac.Fraction as interfaces evolve. Good guardrail.

frac/sealed/seqids/loader.go (1)

10-10: No lingering disk references – migration complete.

Verified via ripgrep that there are zero occurrences of

  • github.com/ozontech/seq-db/disk
  • *disk.IndexReader

Import change to storage is correct.

frac/sealed/seqids/provider.go (1)

7-8: LGTM—seqids.NewProvider callers updated
All seqids.NewProvider call sites now use *storage.IndexReader (e.g., in frac/sealed.go) and there are no remaining imports of github.com/ozontech/seq-db/disk. Ready to merge.

@dkharms dkharms merged commit e10dd87 into main Aug 22, 2025
5 checks passed
@dkharms dkharms deleted the 38-storage-package branch August 22, 2025 11:49
@coderabbitai coderabbitai Bot mentioned this pull request Aug 22, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants