gitx.do 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/blame.d.ts +259 -0
- package/dist/cli/commands/blame.d.ts.map +1 -0
- package/dist/cli/commands/blame.js +609 -0
- package/dist/cli/commands/blame.js.map +1 -0
- package/dist/cli/commands/branch.d.ts +249 -0
- package/dist/cli/commands/branch.d.ts.map +1 -0
- package/dist/cli/commands/branch.js +693 -0
- package/dist/cli/commands/branch.js.map +1 -0
- package/dist/cli/commands/commit.d.ts +182 -0
- package/dist/cli/commands/commit.d.ts.map +1 -0
- package/dist/cli/commands/commit.js +437 -0
- package/dist/cli/commands/commit.js.map +1 -0
- package/dist/cli/commands/diff.d.ts +464 -0
- package/dist/cli/commands/diff.d.ts.map +1 -0
- package/dist/cli/commands/diff.js +958 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/log.d.ts +239 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +535 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/review.d.ts +457 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +533 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/status.d.ts +269 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +493 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/web.d.ts +199 -0
- package/dist/cli/commands/web.d.ts.map +1 -0
- package/dist/cli/commands/web.js +696 -0
- package/dist/cli/commands/web.js.map +1 -0
- package/dist/cli/fs-adapter.d.ts +656 -0
- package/dist/cli/fs-adapter.d.ts.map +1 -0
- package/dist/cli/fs-adapter.js +1179 -0
- package/dist/cli/fs-adapter.js.map +1 -0
- package/dist/cli/index.d.ts +387 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +523 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/components/DiffView.d.ts +7 -0
- package/dist/cli/ui/components/DiffView.d.ts.map +1 -0
- package/dist/cli/ui/components/DiffView.js +11 -0
- package/dist/cli/ui/components/DiffView.js.map +1 -0
- package/dist/cli/ui/components/ErrorDisplay.d.ts +6 -0
- package/dist/cli/ui/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/cli/ui/components/ErrorDisplay.js +11 -0
- package/dist/cli/ui/components/ErrorDisplay.js.map +1 -0
- package/dist/cli/ui/components/FuzzySearch.d.ts +9 -0
- package/dist/cli/ui/components/FuzzySearch.d.ts.map +1 -0
- package/dist/cli/ui/components/FuzzySearch.js +12 -0
- package/dist/cli/ui/components/FuzzySearch.js.map +1 -0
- package/dist/cli/ui/components/LoadingSpinner.d.ts +6 -0
- package/dist/cli/ui/components/LoadingSpinner.d.ts.map +1 -0
- package/dist/cli/ui/components/LoadingSpinner.js +10 -0
- package/dist/cli/ui/components/LoadingSpinner.js.map +1 -0
- package/dist/cli/ui/components/NavigationList.d.ts +9 -0
- package/dist/cli/ui/components/NavigationList.d.ts.map +1 -0
- package/dist/cli/ui/components/NavigationList.js +11 -0
- package/dist/cli/ui/components/NavigationList.js.map +1 -0
- package/dist/cli/ui/components/ScrollableContent.d.ts +8 -0
- package/dist/cli/ui/components/ScrollableContent.d.ts.map +1 -0
- package/dist/cli/ui/components/ScrollableContent.js +11 -0
- package/dist/cli/ui/components/ScrollableContent.js.map +1 -0
- package/dist/cli/ui/components/index.d.ts +7 -0
- package/dist/cli/ui/components/index.d.ts.map +1 -0
- package/dist/cli/ui/components/index.js +9 -0
- package/dist/cli/ui/components/index.js.map +1 -0
- package/dist/cli/ui/terminal-ui.d.ts +52 -0
- package/dist/cli/ui/terminal-ui.d.ts.map +1 -0
- package/dist/cli/ui/terminal-ui.js +121 -0
- package/dist/cli/ui/terminal-ui.js.map +1 -0
- package/dist/durable-object/object-store.d.ts +401 -23
- package/dist/durable-object/object-store.d.ts.map +1 -1
- package/dist/durable-object/object-store.js +414 -25
- package/dist/durable-object/object-store.js.map +1 -1
- package/dist/durable-object/schema.d.ts +188 -0
- package/dist/durable-object/schema.d.ts.map +1 -1
- package/dist/durable-object/schema.js +160 -0
- package/dist/durable-object/schema.js.map +1 -1
- package/dist/durable-object/wal.d.ts +336 -31
- package/dist/durable-object/wal.d.ts.map +1 -1
- package/dist/durable-object/wal.js +272 -27
- package/dist/durable-object/wal.js.map +1 -1
- package/dist/index.d.ts +379 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +379 -7
- package/dist/index.js.map +1 -1
- package/dist/mcp/adapter.d.ts +579 -38
- package/dist/mcp/adapter.d.ts.map +1 -1
- package/dist/mcp/adapter.js +426 -33
- package/dist/mcp/adapter.js.map +1 -1
- package/dist/mcp/sandbox.d.ts +532 -29
- package/dist/mcp/sandbox.d.ts.map +1 -1
- package/dist/mcp/sandbox.js +389 -22
- package/dist/mcp/sandbox.js.map +1 -1
- package/dist/mcp/sdk-adapter.d.ts +478 -56
- package/dist/mcp/sdk-adapter.d.ts.map +1 -1
- package/dist/mcp/sdk-adapter.js +346 -44
- package/dist/mcp/sdk-adapter.js.map +1 -1
- package/dist/mcp/tools.d.ts +445 -30
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +363 -33
- package/dist/mcp/tools.js.map +1 -1
- package/dist/ops/blame.d.ts +424 -21
- package/dist/ops/blame.d.ts.map +1 -1
- package/dist/ops/blame.js +303 -20
- package/dist/ops/blame.js.map +1 -1
- package/dist/ops/branch.d.ts +583 -32
- package/dist/ops/branch.d.ts.map +1 -1
- package/dist/ops/branch.js +365 -23
- package/dist/ops/branch.js.map +1 -1
- package/dist/ops/commit-traversal.d.ts +164 -24
- package/dist/ops/commit-traversal.d.ts.map +1 -1
- package/dist/ops/commit-traversal.js +68 -2
- package/dist/ops/commit-traversal.js.map +1 -1
- package/dist/ops/commit.d.ts +387 -53
- package/dist/ops/commit.d.ts.map +1 -1
- package/dist/ops/commit.js +249 -29
- package/dist/ops/commit.js.map +1 -1
- package/dist/ops/merge-base.d.ts +195 -21
- package/dist/ops/merge-base.d.ts.map +1 -1
- package/dist/ops/merge-base.js +122 -12
- package/dist/ops/merge-base.js.map +1 -1
- package/dist/ops/merge.d.ts +600 -130
- package/dist/ops/merge.d.ts.map +1 -1
- package/dist/ops/merge.js +408 -60
- package/dist/ops/merge.js.map +1 -1
- package/dist/ops/tag.d.ts +67 -2
- package/dist/ops/tag.d.ts.map +1 -1
- package/dist/ops/tag.js +42 -1
- package/dist/ops/tag.js.map +1 -1
- package/dist/ops/tree-builder.d.ts +102 -6
- package/dist/ops/tree-builder.d.ts.map +1 -1
- package/dist/ops/tree-builder.js +30 -5
- package/dist/ops/tree-builder.js.map +1 -1
- package/dist/ops/tree-diff.d.ts +50 -2
- package/dist/ops/tree-diff.d.ts.map +1 -1
- package/dist/ops/tree-diff.js +50 -2
- package/dist/ops/tree-diff.js.map +1 -1
- package/dist/pack/delta.d.ts +211 -39
- package/dist/pack/delta.d.ts.map +1 -1
- package/dist/pack/delta.js +232 -46
- package/dist/pack/delta.js.map +1 -1
- package/dist/pack/format.d.ts +390 -28
- package/dist/pack/format.d.ts.map +1 -1
- package/dist/pack/format.js +344 -33
- package/dist/pack/format.js.map +1 -1
- package/dist/pack/full-generation.d.ts +313 -28
- package/dist/pack/full-generation.d.ts.map +1 -1
- package/dist/pack/full-generation.js +238 -19
- package/dist/pack/full-generation.js.map +1 -1
- package/dist/pack/generation.d.ts +346 -23
- package/dist/pack/generation.d.ts.map +1 -1
- package/dist/pack/generation.js +269 -21
- package/dist/pack/generation.js.map +1 -1
- package/dist/pack/index.d.ts +407 -86
- package/dist/pack/index.d.ts.map +1 -1
- package/dist/pack/index.js +351 -70
- package/dist/pack/index.js.map +1 -1
- package/dist/refs/branch.d.ts +517 -71
- package/dist/refs/branch.d.ts.map +1 -1
- package/dist/refs/branch.js +410 -26
- package/dist/refs/branch.js.map +1 -1
- package/dist/refs/storage.d.ts +610 -57
- package/dist/refs/storage.d.ts.map +1 -1
- package/dist/refs/storage.js +481 -29
- package/dist/refs/storage.js.map +1 -1
- package/dist/refs/tag.d.ts +677 -67
- package/dist/refs/tag.d.ts.map +1 -1
- package/dist/refs/tag.js +497 -30
- package/dist/refs/tag.js.map +1 -1
- package/dist/storage/lru-cache.d.ts +556 -53
- package/dist/storage/lru-cache.d.ts.map +1 -1
- package/dist/storage/lru-cache.js +439 -36
- package/dist/storage/lru-cache.js.map +1 -1
- package/dist/storage/object-index.d.ts +483 -38
- package/dist/storage/object-index.d.ts.map +1 -1
- package/dist/storage/object-index.js +388 -22
- package/dist/storage/object-index.js.map +1 -1
- package/dist/storage/r2-pack.d.ts +957 -94
- package/dist/storage/r2-pack.d.ts.map +1 -1
- package/dist/storage/r2-pack.js +756 -48
- package/dist/storage/r2-pack.js.map +1 -1
- package/dist/tiered/cdc-pipeline.d.ts +1610 -38
- package/dist/tiered/cdc-pipeline.d.ts.map +1 -1
- package/dist/tiered/cdc-pipeline.js +1131 -22
- package/dist/tiered/cdc-pipeline.js.map +1 -1
- package/dist/tiered/migration.d.ts +903 -41
- package/dist/tiered/migration.d.ts.map +1 -1
- package/dist/tiered/migration.js +646 -24
- package/dist/tiered/migration.js.map +1 -1
- package/dist/tiered/parquet-writer.d.ts +944 -47
- package/dist/tiered/parquet-writer.d.ts.map +1 -1
- package/dist/tiered/parquet-writer.js +667 -39
- package/dist/tiered/parquet-writer.js.map +1 -1
- package/dist/tiered/read-path.d.ts +728 -34
- package/dist/tiered/read-path.d.ts.map +1 -1
- package/dist/tiered/read-path.js +310 -27
- package/dist/tiered/read-path.js.map +1 -1
- package/dist/types/objects.d.ts +457 -0
- package/dist/types/objects.d.ts.map +1 -1
- package/dist/types/objects.js +305 -4
- package/dist/types/objects.js.map +1 -1
- package/dist/types/storage.d.ts +407 -35
- package/dist/types/storage.d.ts.map +1 -1
- package/dist/types/storage.js +27 -3
- package/dist/types/storage.js.map +1 -1
- package/dist/utils/hash.d.ts +133 -12
- package/dist/utils/hash.d.ts.map +1 -1
- package/dist/utils/hash.js +133 -12
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/sha1.d.ts +102 -9
- package/dist/utils/sha1.d.ts.map +1 -1
- package/dist/utils/sha1.js +114 -11
- package/dist/utils/sha1.js.map +1 -1
- package/dist/wire/capabilities.d.ts +896 -88
- package/dist/wire/capabilities.d.ts.map +1 -1
- package/dist/wire/capabilities.js +566 -62
- package/dist/wire/capabilities.js.map +1 -1
- package/dist/wire/pkt-line.d.ts +293 -15
- package/dist/wire/pkt-line.d.ts.map +1 -1
- package/dist/wire/pkt-line.js +251 -15
- package/dist/wire/pkt-line.js.map +1 -1
- package/dist/wire/receive-pack.d.ts +814 -64
- package/dist/wire/receive-pack.d.ts.map +1 -1
- package/dist/wire/receive-pack.js +542 -41
- package/dist/wire/receive-pack.js.map +1 -1
- package/dist/wire/smart-http.d.ts +575 -97
- package/dist/wire/smart-http.d.ts.map +1 -1
- package/dist/wire/smart-http.js +337 -46
- package/dist/wire/smart-http.js.map +1 -1
- package/dist/wire/upload-pack.d.ts +492 -98
- package/dist/wire/upload-pack.d.ts.map +1 -1
- package/dist/wire/upload-pack.js +347 -59
- package/dist/wire/upload-pack.js.map +1 -1
- package/package.json +10 -2
|
@@ -1,87 +1,554 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tiered Read Path
|
|
2
|
+
* @fileoverview Tiered Read Path Module
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* @description
|
|
5
|
+
* Implements reading objects from a multi-tier storage system designed for
|
|
6
|
+
* Git object storage. The tiered approach optimizes for both performance and
|
|
7
|
+
* cost by organizing data across multiple storage layers with different
|
|
8
|
+
* characteristics:
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
10
|
+
* **Storage Tiers:**
|
|
11
|
+
* - **Hot tier**: Durable Object SQLite (fastest, local, highest cost)
|
|
12
|
+
* - **Warm tier**: R2 object storage (medium latency, packed objects)
|
|
13
|
+
* - **Cold tier**: Analytics/Parquet (highest latency, lowest cost)
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* **Features:**
|
|
16
|
+
* - Automatic tier fallback on cache miss
|
|
17
|
+
* - Read-through caching with promotion to hotter tiers
|
|
18
|
+
* - Configurable promotion policies (aggressive, conservative, none)
|
|
19
|
+
* - Latency tracking for performance monitoring
|
|
20
|
+
*
|
|
21
|
+
* **Architecture:**
|
|
22
|
+
* The TieredReader orchestrates reads across all tiers, attempting to serve
|
|
23
|
+
* data from the fastest available tier while optionally promoting frequently
|
|
24
|
+
* accessed objects to faster tiers.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Create a tiered reader with all backends
|
|
29
|
+
* const reader = new TieredReader(
|
|
30
|
+
* hotBackend,
|
|
31
|
+
* warmBackend,
|
|
32
|
+
* coldBackend,
|
|
33
|
+
* {
|
|
34
|
+
* hot: { enabled: true, maxSize: 1024 * 1024 },
|
|
35
|
+
* warm: { enabled: true },
|
|
36
|
+
* cold: { enabled: true },
|
|
37
|
+
* promotionPolicy: 'aggressive'
|
|
38
|
+
* }
|
|
39
|
+
* )
|
|
40
|
+
*
|
|
41
|
+
* // Read an object - will try hot -> warm -> cold
|
|
42
|
+
* const result = await reader.read('abc123...')
|
|
43
|
+
* if (result.object) {
|
|
44
|
+
* console.log(`Found in ${result.tier} tier`)
|
|
45
|
+
* console.log(`Latency: ${result.latencyMs}ms`)
|
|
46
|
+
* if (result.promoted) {
|
|
47
|
+
* console.log('Object was promoted to hot tier')
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @module tiered/read-path
|
|
53
|
+
* @see {@link TieredReader} - Main implementation class
|
|
54
|
+
* @see {@link TieredStorageConfig} - Configuration options
|
|
15
55
|
*/
|
|
16
56
|
import { ObjectType } from '../types/objects';
|
|
17
57
|
/**
|
|
18
|
-
*
|
|
58
|
+
* Represents a Git object stored in the tiered storage system.
|
|
59
|
+
*
|
|
60
|
+
* @description
|
|
61
|
+
* StoredObject is the common representation of a Git object across all storage
|
|
62
|
+
* tiers. It contains the object's content, metadata, and timing information
|
|
63
|
+
* needed for cache management and analytics.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const blobObject: StoredObject = {
|
|
68
|
+
* sha: 'a1b2c3d4e5f6...',
|
|
69
|
+
* type: 'blob',
|
|
70
|
+
* size: 1024,
|
|
71
|
+
* data: new Uint8Array([...]),
|
|
72
|
+
* createdAt: Date.now()
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @interface StoredObject
|
|
19
77
|
*/
|
|
20
78
|
export interface StoredObject {
|
|
79
|
+
/**
|
|
80
|
+
* SHA-1 hash of the object content.
|
|
81
|
+
* Must be a 40-character hexadecimal string.
|
|
82
|
+
*
|
|
83
|
+
* @example 'a1b2c3d4e5f678901234567890abcdef12345678'
|
|
84
|
+
*/
|
|
21
85
|
sha: string;
|
|
86
|
+
/**
|
|
87
|
+
* Git object type (blob, tree, commit, or tag).
|
|
88
|
+
*
|
|
89
|
+
* @see {@link ObjectType}
|
|
90
|
+
*/
|
|
22
91
|
type: ObjectType;
|
|
92
|
+
/**
|
|
93
|
+
* Size of the uncompressed object data in bytes.
|
|
94
|
+
*/
|
|
23
95
|
size: number;
|
|
96
|
+
/**
|
|
97
|
+
* Raw object data as a byte array.
|
|
98
|
+
* This is the uncompressed content of the Git object.
|
|
99
|
+
*/
|
|
24
100
|
data: Uint8Array;
|
|
101
|
+
/**
|
|
102
|
+
* Unix timestamp (milliseconds) when the object was first stored.
|
|
103
|
+
* Used for TTL calculations and analytics.
|
|
104
|
+
*/
|
|
25
105
|
createdAt: number;
|
|
26
106
|
}
|
|
27
107
|
/**
|
|
28
|
-
* Configuration for a single tier
|
|
108
|
+
* Configuration options for a single storage tier.
|
|
109
|
+
*
|
|
110
|
+
* @description
|
|
111
|
+
* Each tier can be individually enabled/disabled and configured with
|
|
112
|
+
* size limits and TTL (time-to-live) settings. This allows fine-grained
|
|
113
|
+
* control over which objects are stored in each tier.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* // Hot tier with size limit and TTL
|
|
118
|
+
* const hotConfig: TierConfig = {
|
|
119
|
+
* enabled: true,
|
|
120
|
+
* maxSize: 1024 * 1024, // 1MB max object size
|
|
121
|
+
* ttl: 3600 * 1000 // 1 hour TTL
|
|
122
|
+
* }
|
|
123
|
+
*
|
|
124
|
+
* // Disabled tier
|
|
125
|
+
* const disabledConfig: TierConfig = {
|
|
126
|
+
* enabled: false
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @interface TierConfig
|
|
29
131
|
*/
|
|
30
132
|
export interface TierConfig {
|
|
133
|
+
/**
|
|
134
|
+
* Whether this tier is enabled for reads and writes.
|
|
135
|
+
* Disabled tiers are skipped during read operations.
|
|
136
|
+
*/
|
|
31
137
|
enabled: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Maximum object size in bytes that can be stored in this tier.
|
|
140
|
+
* Objects larger than this size will not be promoted to this tier.
|
|
141
|
+
* If undefined, no size limit is enforced.
|
|
142
|
+
*
|
|
143
|
+
* @example 1048576 // 1MB
|
|
144
|
+
*/
|
|
32
145
|
maxSize?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Time-to-live in milliseconds for objects in this tier.
|
|
148
|
+
* Objects older than TTL may be evicted or migrated to colder tiers.
|
|
149
|
+
* If undefined, objects persist indefinitely.
|
|
150
|
+
*
|
|
151
|
+
* @example 3600000 // 1 hour
|
|
152
|
+
*/
|
|
33
153
|
ttl?: number;
|
|
34
154
|
}
|
|
35
155
|
/**
|
|
36
|
-
*
|
|
156
|
+
* Complete configuration for the tiered storage system.
|
|
157
|
+
*
|
|
158
|
+
* @description
|
|
159
|
+
* Defines the behavior of all three storage tiers (hot, warm, cold) and
|
|
160
|
+
* the promotion policy that determines when objects are moved to faster tiers.
|
|
161
|
+
*
|
|
162
|
+
* **Promotion Policies:**
|
|
163
|
+
* - `aggressive`: Immediately promote objects to hot tier on first access
|
|
164
|
+
* - `conservative`: Only promote on repeated access (not yet implemented)
|
|
165
|
+
* - `none`: Never automatically promote objects
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const config: TieredStorageConfig = {
|
|
170
|
+
* hot: {
|
|
171
|
+
* enabled: true,
|
|
172
|
+
* maxSize: 1024 * 1024, // 1MB max
|
|
173
|
+
* ttl: 3600 * 1000 // 1 hour
|
|
174
|
+
* },
|
|
175
|
+
* warm: {
|
|
176
|
+
* enabled: true,
|
|
177
|
+
* maxSize: 10 * 1024 * 1024 // 10MB max
|
|
178
|
+
* },
|
|
179
|
+
* cold: {
|
|
180
|
+
* enabled: true
|
|
181
|
+
* // No size limit for cold storage
|
|
182
|
+
* },
|
|
183
|
+
* promotionPolicy: 'aggressive'
|
|
184
|
+
* }
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @interface TieredStorageConfig
|
|
37
188
|
*/
|
|
38
189
|
export interface TieredStorageConfig {
|
|
190
|
+
/**
|
|
191
|
+
* Configuration for the hot tier (Durable Object SQLite).
|
|
192
|
+
* Hot tier provides the fastest access but has limited capacity.
|
|
193
|
+
*/
|
|
39
194
|
hot: TierConfig;
|
|
195
|
+
/**
|
|
196
|
+
* Configuration for the warm tier (R2 object storage).
|
|
197
|
+
* Warm tier provides moderate latency with larger capacity.
|
|
198
|
+
*/
|
|
40
199
|
warm: TierConfig;
|
|
200
|
+
/**
|
|
201
|
+
* Configuration for the cold tier (Analytics/Parquet).
|
|
202
|
+
* Cold tier provides lowest cost storage for archival.
|
|
203
|
+
*/
|
|
41
204
|
cold: TierConfig;
|
|
205
|
+
/**
|
|
206
|
+
* Policy for promoting objects to hotter tiers.
|
|
207
|
+
*
|
|
208
|
+
* - `aggressive`: Promote on first read from colder tier
|
|
209
|
+
* - `conservative`: Promote only on repeated access
|
|
210
|
+
* - `none`: Never automatically promote
|
|
211
|
+
*/
|
|
42
212
|
promotionPolicy: 'aggressive' | 'conservative' | 'none';
|
|
43
213
|
}
|
|
44
214
|
/**
|
|
45
|
-
* Result of a read operation
|
|
215
|
+
* Result of a read operation from the tiered storage system.
|
|
216
|
+
*
|
|
217
|
+
* @description
|
|
218
|
+
* ReadResult provides complete information about a read operation, including
|
|
219
|
+
* the retrieved object (if found), which tier served the request, whether
|
|
220
|
+
* the object was promoted, and latency metrics.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* const result = await reader.read(sha)
|
|
225
|
+
*
|
|
226
|
+
* if (result.object) {
|
|
227
|
+
* console.log(`Object found in ${result.tier} tier`)
|
|
228
|
+
* console.log(`Size: ${result.object.size} bytes`)
|
|
229
|
+
* console.log(`Latency: ${result.latencyMs}ms`)
|
|
230
|
+
*
|
|
231
|
+
* if (result.promoted) {
|
|
232
|
+
* console.log('Object was promoted to hot tier for faster future access')
|
|
233
|
+
* }
|
|
234
|
+
* } else {
|
|
235
|
+
* console.log('Object not found in any tier')
|
|
236
|
+
* console.log(`Search took ${result.latencyMs}ms`)
|
|
237
|
+
* }
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @interface ReadResult
|
|
46
241
|
*/
|
|
47
242
|
export interface ReadResult {
|
|
243
|
+
/**
|
|
244
|
+
* The retrieved object, or null if not found in any tier.
|
|
245
|
+
*/
|
|
48
246
|
object: StoredObject | null;
|
|
247
|
+
/**
|
|
248
|
+
* The tier that served the request, or null if object was not found.
|
|
249
|
+
*/
|
|
49
250
|
tier: 'hot' | 'warm' | 'cold' | null;
|
|
251
|
+
/**
|
|
252
|
+
* Whether the object was promoted to a hotter tier during this read.
|
|
253
|
+
* Only true if the object was found in warm/cold tier and successfully
|
|
254
|
+
* copied to the hot tier.
|
|
255
|
+
*/
|
|
50
256
|
promoted: boolean;
|
|
257
|
+
/**
|
|
258
|
+
* Total latency of the read operation in milliseconds.
|
|
259
|
+
* Includes time spent checking all tiers and any promotion overhead.
|
|
260
|
+
*/
|
|
51
261
|
latencyMs: number;
|
|
52
262
|
}
|
|
53
263
|
/**
|
|
54
|
-
* Interface for the tiered object store
|
|
264
|
+
* Interface for the tiered object store.
|
|
265
|
+
*
|
|
266
|
+
* @description
|
|
267
|
+
* Defines the public API for interacting with the tiered storage system.
|
|
268
|
+
* Implementations must provide methods for reading from any tier,
|
|
269
|
+
* manual promotion, and configuration access.
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* class MyTieredStore implements TieredObjectStore {
|
|
274
|
+
* async read(sha: string): Promise<ReadResult> {
|
|
275
|
+
* // Implementation
|
|
276
|
+
* }
|
|
277
|
+
* // ... other methods
|
|
278
|
+
* }
|
|
279
|
+
* ```
|
|
280
|
+
*
|
|
281
|
+
* @interface TieredObjectStore
|
|
55
282
|
*/
|
|
56
283
|
export interface TieredObjectStore {
|
|
284
|
+
/**
|
|
285
|
+
* Reads an object from the tiered storage system.
|
|
286
|
+
*
|
|
287
|
+
* @description
|
|
288
|
+
* Attempts to read the object from each enabled tier in order
|
|
289
|
+
* (hot -> warm -> cold), returning as soon as the object is found.
|
|
290
|
+
* May promote the object to the hot tier based on the promotion policy.
|
|
291
|
+
*
|
|
292
|
+
* @param sha - The 40-character SHA-1 hash of the object to read
|
|
293
|
+
* @returns Promise resolving to the read result
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* ```typescript
|
|
297
|
+
* const result = await store.read('abc123...')
|
|
298
|
+
* if (result.object) {
|
|
299
|
+
* // Process the object data
|
|
300
|
+
* }
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
57
303
|
read(sha: string): Promise<ReadResult>;
|
|
304
|
+
/**
|
|
305
|
+
* Reads an object directly from the hot tier only.
|
|
306
|
+
*
|
|
307
|
+
* @description
|
|
308
|
+
* Bypasses the tier fallback logic to read directly from the hot tier.
|
|
309
|
+
* Useful for checking if an object is already cached.
|
|
310
|
+
*
|
|
311
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
312
|
+
* @returns Promise resolving to the object or null if not in hot tier
|
|
313
|
+
*/
|
|
58
314
|
readFromHot(sha: string): Promise<StoredObject | null>;
|
|
315
|
+
/**
|
|
316
|
+
* Reads an object directly from the warm tier only.
|
|
317
|
+
*
|
|
318
|
+
* @description
|
|
319
|
+
* Bypasses the tier fallback logic to read directly from the warm tier.
|
|
320
|
+
* Does not trigger promotion to the hot tier.
|
|
321
|
+
*
|
|
322
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
323
|
+
* @returns Promise resolving to the object or null if not in warm tier
|
|
324
|
+
*/
|
|
59
325
|
readFromWarm(sha: string): Promise<StoredObject | null>;
|
|
326
|
+
/**
|
|
327
|
+
* Reads an object directly from the cold tier only.
|
|
328
|
+
*
|
|
329
|
+
* @description
|
|
330
|
+
* Bypasses the tier fallback logic to read directly from the cold tier.
|
|
331
|
+
* Does not trigger promotion to hotter tiers.
|
|
332
|
+
*
|
|
333
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
334
|
+
* @returns Promise resolving to the object or null if not in cold tier
|
|
335
|
+
*/
|
|
60
336
|
readFromCold(sha: string): Promise<StoredObject | null>;
|
|
337
|
+
/**
|
|
338
|
+
* Manually promotes an object to the hot tier.
|
|
339
|
+
*
|
|
340
|
+
* @description
|
|
341
|
+
* Copies the provided object to the hot tier storage. This is useful for
|
|
342
|
+
* pre-warming the cache or manually controlling tier placement.
|
|
343
|
+
*
|
|
344
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
345
|
+
* @param object - The complete stored object to promote
|
|
346
|
+
* @returns Promise that resolves when promotion is complete
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```typescript
|
|
350
|
+
* // Pre-warm the cache with frequently accessed objects
|
|
351
|
+
* for (const obj of frequentObjects) {
|
|
352
|
+
* await store.promoteToHot(obj.sha, obj)
|
|
353
|
+
* }
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
61
356
|
promoteToHot(sha: string, object: StoredObject): Promise<void>;
|
|
357
|
+
/**
|
|
358
|
+
* Returns the current storage configuration.
|
|
359
|
+
*
|
|
360
|
+
* @returns The tiered storage configuration
|
|
361
|
+
*/
|
|
62
362
|
getConfig(): TieredStorageConfig;
|
|
63
363
|
}
|
|
64
364
|
/**
|
|
65
|
-
*
|
|
365
|
+
* Backend interface for the hot tier (Durable Object SQLite).
|
|
366
|
+
*
|
|
367
|
+
* @description
|
|
368
|
+
* The hot tier backend provides fast, local storage using Durable Object
|
|
369
|
+
* SQLite. It supports full CRUD operations for Git objects.
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```typescript
|
|
373
|
+
* class SqliteHotBackend implements HotTierBackend {
|
|
374
|
+
* async get(sha: string): Promise<StoredObject | null> {
|
|
375
|
+
* const row = await this.db.get('SELECT * FROM objects WHERE sha = ?', sha)
|
|
376
|
+
* return row ? this.rowToObject(row) : null
|
|
377
|
+
* }
|
|
378
|
+
*
|
|
379
|
+
* async put(sha: string, object: StoredObject): Promise<void> {
|
|
380
|
+
* await this.db.run(
|
|
381
|
+
* 'INSERT OR REPLACE INTO objects VALUES (?, ?, ?, ?, ?)',
|
|
382
|
+
* sha, object.type, object.size, object.data, object.createdAt
|
|
383
|
+
* )
|
|
384
|
+
* }
|
|
385
|
+
*
|
|
386
|
+
* async delete(sha: string): Promise<boolean> {
|
|
387
|
+
* const result = await this.db.run('DELETE FROM objects WHERE sha = ?', sha)
|
|
388
|
+
* return result.changes > 0
|
|
389
|
+
* }
|
|
390
|
+
*
|
|
391
|
+
* async has(sha: string): Promise<boolean> {
|
|
392
|
+
* const row = await this.db.get('SELECT 1 FROM objects WHERE sha = ?', sha)
|
|
393
|
+
* return !!row
|
|
394
|
+
* }
|
|
395
|
+
* }
|
|
396
|
+
* ```
|
|
397
|
+
*
|
|
398
|
+
* @interface HotTierBackend
|
|
66
399
|
*/
|
|
67
400
|
export interface HotTierBackend {
|
|
401
|
+
/**
|
|
402
|
+
* Retrieves an object from the hot tier.
|
|
403
|
+
*
|
|
404
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
405
|
+
* @returns Promise resolving to the object or null if not found
|
|
406
|
+
*/
|
|
68
407
|
get(sha: string): Promise<StoredObject | null>;
|
|
408
|
+
/**
|
|
409
|
+
* Stores an object in the hot tier.
|
|
410
|
+
*
|
|
411
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
412
|
+
* @param object - The complete stored object to write
|
|
413
|
+
* @returns Promise that resolves when the write is complete
|
|
414
|
+
*/
|
|
69
415
|
put(sha: string, object: StoredObject): Promise<void>;
|
|
416
|
+
/**
|
|
417
|
+
* Deletes an object from the hot tier.
|
|
418
|
+
*
|
|
419
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
420
|
+
* @returns Promise resolving to true if object was deleted, false if not found
|
|
421
|
+
*/
|
|
70
422
|
delete(sha: string): Promise<boolean>;
|
|
423
|
+
/**
|
|
424
|
+
* Checks if an object exists in the hot tier.
|
|
425
|
+
*
|
|
426
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
427
|
+
* @returns Promise resolving to true if object exists
|
|
428
|
+
*/
|
|
71
429
|
has(sha: string): Promise<boolean>;
|
|
72
430
|
}
|
|
73
431
|
/**
|
|
74
|
-
*
|
|
432
|
+
* Backend interface for the warm tier (R2 object storage).
|
|
433
|
+
*
|
|
434
|
+
* @description
|
|
435
|
+
* The warm tier backend provides access to objects stored in R2, either
|
|
436
|
+
* as individual objects or within packfiles. Packfile access allows
|
|
437
|
+
* efficient retrieval of objects that have been packed together.
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```typescript
|
|
441
|
+
* class R2WarmBackend implements WarmTierBackend {
|
|
442
|
+
* async get(sha: string): Promise<StoredObject | null> {
|
|
443
|
+
* // Try direct object first
|
|
444
|
+
* const obj = await this.r2.get(`objects/${sha}`)
|
|
445
|
+
* if (obj) return this.parseObject(obj)
|
|
446
|
+
*
|
|
447
|
+
* // Fall back to pack lookup
|
|
448
|
+
* const location = await this.index.findInPack(sha)
|
|
449
|
+
* if (location) {
|
|
450
|
+
* return this.getFromPack(location.packId, location.offset)
|
|
451
|
+
* }
|
|
452
|
+
* return null
|
|
453
|
+
* }
|
|
454
|
+
*
|
|
455
|
+
* async getFromPack(packId: string, offset: number): Promise<StoredObject | null> {
|
|
456
|
+
* const pack = await this.r2.get(`packs/${packId}`)
|
|
457
|
+
* return pack ? this.extractFromPack(pack, offset) : null
|
|
458
|
+
* }
|
|
459
|
+
* }
|
|
460
|
+
* ```
|
|
461
|
+
*
|
|
462
|
+
* @interface WarmTierBackend
|
|
75
463
|
*/
|
|
76
464
|
export interface WarmTierBackend {
|
|
465
|
+
/**
|
|
466
|
+
* Retrieves an object from the warm tier.
|
|
467
|
+
*
|
|
468
|
+
* @description
|
|
469
|
+
* May retrieve the object either directly or from a packfile,
|
|
470
|
+
* depending on how it was stored.
|
|
471
|
+
*
|
|
472
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
473
|
+
* @returns Promise resolving to the object or null if not found
|
|
474
|
+
*/
|
|
77
475
|
get(sha: string): Promise<StoredObject | null>;
|
|
476
|
+
/**
|
|
477
|
+
* Retrieves an object from a specific packfile at a given offset.
|
|
478
|
+
*
|
|
479
|
+
* @description
|
|
480
|
+
* Used when the exact location of an object within a packfile is known,
|
|
481
|
+
* typically from an index lookup.
|
|
482
|
+
*
|
|
483
|
+
* @param packId - The identifier of the packfile
|
|
484
|
+
* @param offset - Byte offset of the object within the pack
|
|
485
|
+
* @returns Promise resolving to the object or null if not found
|
|
486
|
+
*/
|
|
78
487
|
getFromPack(packId: string, offset: number): Promise<StoredObject | null>;
|
|
79
488
|
}
|
|
80
489
|
/**
|
|
81
|
-
*
|
|
490
|
+
* Backend interface for the cold tier (Analytics/Parquet).
|
|
491
|
+
*
|
|
492
|
+
* @description
|
|
493
|
+
* The cold tier backend provides access to objects stored in analytical
|
|
494
|
+
* formats like Parquet. It supports both direct lookups and filtered
|
|
495
|
+
* queries for analytics purposes.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```typescript
|
|
499
|
+
* class ParquetColdBackend implements ColdTierBackend {
|
|
500
|
+
* async get(sha: string): Promise<StoredObject | null> {
|
|
501
|
+
* const rows = await this.parquet.query(`
|
|
502
|
+
* SELECT * FROM objects WHERE sha = '${sha}'
|
|
503
|
+
* `)
|
|
504
|
+
* return rows[0] ? this.rowToObject(rows[0]) : null
|
|
505
|
+
* }
|
|
506
|
+
*
|
|
507
|
+
* async query(filter: { type?: ObjectType }): Promise<StoredObject[]> {
|
|
508
|
+
* const conditions = []
|
|
509
|
+
* if (filter.type) conditions.push(`type = '${filter.type}'`)
|
|
510
|
+
* if (filter.minSize) conditions.push(`size >= ${filter.minSize}`)
|
|
511
|
+
*
|
|
512
|
+
* const sql = `SELECT * FROM objects WHERE ${conditions.join(' AND ')}`
|
|
513
|
+
* const rows = await this.parquet.query(sql)
|
|
514
|
+
* return rows.map(this.rowToObject)
|
|
515
|
+
* }
|
|
516
|
+
* }
|
|
517
|
+
* ```
|
|
518
|
+
*
|
|
519
|
+
* @interface ColdTierBackend
|
|
82
520
|
*/
|
|
83
521
|
export interface ColdTierBackend {
|
|
522
|
+
/**
|
|
523
|
+
* Retrieves an object from the cold tier by SHA.
|
|
524
|
+
*
|
|
525
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
526
|
+
* @returns Promise resolving to the object or null if not found
|
|
527
|
+
*/
|
|
84
528
|
get(sha: string): Promise<StoredObject | null>;
|
|
529
|
+
/**
|
|
530
|
+
* Queries the cold tier for objects matching the given filter.
|
|
531
|
+
*
|
|
532
|
+
* @description
|
|
533
|
+
* Performs a filtered query against the analytical storage, returning
|
|
534
|
+
* all objects that match the specified criteria. Useful for analytics
|
|
535
|
+
* and batch processing operations.
|
|
536
|
+
*
|
|
537
|
+
* @param filter - Filter criteria for the query
|
|
538
|
+
* @param filter.type - Filter by Git object type
|
|
539
|
+
* @param filter.minSize - Minimum object size in bytes
|
|
540
|
+
* @param filter.maxSize - Maximum object size in bytes
|
|
541
|
+
* @returns Promise resolving to array of matching objects
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* // Find all large blobs
|
|
546
|
+
* const largeBlobs = await coldBackend.query({
|
|
547
|
+
* type: 'blob',
|
|
548
|
+
* minSize: 1024 * 1024 // > 1MB
|
|
549
|
+
* })
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
85
552
|
query(filter: {
|
|
86
553
|
type?: ObjectType;
|
|
87
554
|
minSize?: number;
|
|
@@ -89,51 +556,278 @@ export interface ColdTierBackend {
|
|
|
89
556
|
}): Promise<StoredObject[]>;
|
|
90
557
|
}
|
|
91
558
|
/**
|
|
92
|
-
* TieredReader - Main implementation of the tiered read path
|
|
559
|
+
* TieredReader - Main implementation of the tiered read path.
|
|
560
|
+
*
|
|
561
|
+
* @description
|
|
562
|
+
* TieredReader orchestrates reads across multiple storage tiers (hot, warm, cold),
|
|
563
|
+
* implementing automatic fallback and optional promotion to hotter tiers. It provides
|
|
564
|
+
* a unified interface for reading Git objects regardless of which tier they reside in.
|
|
565
|
+
*
|
|
566
|
+
* **Read Algorithm:**
|
|
567
|
+
* 1. Validate the SHA-1 hash
|
|
568
|
+
* 2. If hot tier enabled, attempt to read from hot tier
|
|
569
|
+
* 3. If not found and warm tier enabled, attempt warm tier
|
|
570
|
+
* 4. If not found and cold tier enabled, attempt cold tier
|
|
571
|
+
* 5. If found in warm/cold, optionally promote to hot tier
|
|
572
|
+
* 6. Return result with object, source tier, and metrics
|
|
573
|
+
*
|
|
574
|
+
* **Promotion Policies:**
|
|
575
|
+
* - `aggressive`: Immediately promote any object read from warm/cold to hot
|
|
576
|
+
* - `conservative`: Reserved for future implementation (repeated access tracking)
|
|
577
|
+
* - `none`: Never automatically promote objects
|
|
93
578
|
*
|
|
94
|
-
*
|
|
95
|
-
* and
|
|
579
|
+
* **Error Handling:**
|
|
580
|
+
* Individual tier failures are silently caught and the next tier is tried.
|
|
581
|
+
* This ensures graceful degradation when a tier is temporarily unavailable.
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* ```typescript
|
|
585
|
+
* // Create backends for each tier
|
|
586
|
+
* const hotBackend = new SqliteHotBackend(db)
|
|
587
|
+
* const warmBackend = new R2WarmBackend(r2)
|
|
588
|
+
* const coldBackend = new ParquetColdBackend(parquet)
|
|
589
|
+
*
|
|
590
|
+
* // Configure the tiered storage
|
|
591
|
+
* const config: TieredStorageConfig = {
|
|
592
|
+
* hot: { enabled: true, maxSize: 1024 * 1024 },
|
|
593
|
+
* warm: { enabled: true },
|
|
594
|
+
* cold: { enabled: true },
|
|
595
|
+
* promotionPolicy: 'aggressive'
|
|
596
|
+
* }
|
|
597
|
+
*
|
|
598
|
+
* // Create the reader
|
|
599
|
+
* const reader = new TieredReader(hotBackend, warmBackend, coldBackend, config)
|
|
600
|
+
*
|
|
601
|
+
* // Read an object
|
|
602
|
+
* const result = await reader.read('a1b2c3d4e5f678901234567890abcdef12345678')
|
|
603
|
+
*
|
|
604
|
+
* if (result.object) {
|
|
605
|
+
* console.log(`Object type: ${result.object.type}`)
|
|
606
|
+
* console.log(`Size: ${result.object.size} bytes`)
|
|
607
|
+
* console.log(`Served from: ${result.tier} tier`)
|
|
608
|
+
* console.log(`Latency: ${result.latencyMs}ms`)
|
|
609
|
+
*
|
|
610
|
+
* if (result.promoted) {
|
|
611
|
+
* console.log('Object was promoted to hot tier')
|
|
612
|
+
* }
|
|
613
|
+
* } else {
|
|
614
|
+
* console.log('Object not found in any tier')
|
|
615
|
+
* }
|
|
616
|
+
*
|
|
617
|
+
* // Direct tier access
|
|
618
|
+
* const hotOnly = await reader.readFromHot(sha)
|
|
619
|
+
* const warmOnly = await reader.readFromWarm(sha)
|
|
620
|
+
* const coldOnly = await reader.readFromCold(sha)
|
|
621
|
+
*
|
|
622
|
+
* // Manual promotion
|
|
623
|
+
* if (warmOnly) {
|
|
624
|
+
* await reader.promoteToHot(sha, warmOnly)
|
|
625
|
+
* }
|
|
626
|
+
* ```
|
|
627
|
+
*
|
|
628
|
+
* @class TieredReader
|
|
629
|
+
* @implements {TieredObjectStore}
|
|
96
630
|
*/
|
|
97
631
|
export declare class TieredReader implements TieredObjectStore {
|
|
632
|
+
/**
|
|
633
|
+
* Backend for the hot storage tier (Durable Object SQLite).
|
|
634
|
+
* @private
|
|
635
|
+
*/
|
|
98
636
|
private hotBackend;
|
|
637
|
+
/**
|
|
638
|
+
* Backend for the warm storage tier (R2 object storage).
|
|
639
|
+
* @private
|
|
640
|
+
*/
|
|
99
641
|
private warmBackend;
|
|
642
|
+
/**
|
|
643
|
+
* Backend for the cold storage tier (Analytics/Parquet).
|
|
644
|
+
* @private
|
|
645
|
+
*/
|
|
100
646
|
private coldBackend;
|
|
647
|
+
/**
|
|
648
|
+
* Configuration for all tiers and promotion policy.
|
|
649
|
+
* @private
|
|
650
|
+
*/
|
|
101
651
|
private config;
|
|
652
|
+
/**
|
|
653
|
+
* Creates a new TieredReader instance.
|
|
654
|
+
*
|
|
655
|
+
* @param hotBackend - Backend for the hot tier (Durable Object SQLite)
|
|
656
|
+
* @param warmBackend - Backend for the warm tier (R2)
|
|
657
|
+
* @param coldBackend - Backend for the cold tier (Parquet)
|
|
658
|
+
* @param config - Configuration for all tiers and promotion policy
|
|
659
|
+
*
|
|
660
|
+
* @example
|
|
661
|
+
* ```typescript
|
|
662
|
+
* const reader = new TieredReader(
|
|
663
|
+
* hotBackend,
|
|
664
|
+
* warmBackend,
|
|
665
|
+
* coldBackend,
|
|
666
|
+
* {
|
|
667
|
+
* hot: { enabled: true, maxSize: 1024 * 1024 },
|
|
668
|
+
* warm: { enabled: true },
|
|
669
|
+
* cold: { enabled: true },
|
|
670
|
+
* promotionPolicy: 'aggressive'
|
|
671
|
+
* }
|
|
672
|
+
* )
|
|
673
|
+
* ```
|
|
674
|
+
*/
|
|
102
675
|
constructor(hotBackend: HotTierBackend, warmBackend: WarmTierBackend, coldBackend: ColdTierBackend, config: TieredStorageConfig);
|
|
103
676
|
/**
|
|
104
|
-
*
|
|
677
|
+
* Reads an object from the tiered storage system.
|
|
678
|
+
*
|
|
679
|
+
* @description
|
|
680
|
+
* Attempts to read the object from each enabled tier in order
|
|
681
|
+
* (hot -> warm -> cold), returning as soon as the object is found.
|
|
682
|
+
* Objects found in warm or cold tiers may be promoted to hot tier
|
|
683
|
+
* based on the configured promotion policy.
|
|
105
684
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
685
|
+
* **Invalid SHA Handling:**
|
|
686
|
+
* If the SHA is invalid (not 40 hex characters), returns immediately
|
|
687
|
+
* with null object and no tier lookup is performed.
|
|
688
|
+
*
|
|
689
|
+
* **Error Handling:**
|
|
690
|
+
* If a tier fails (throws an error), the error is caught silently
|
|
691
|
+
* and the next tier is attempted. This provides graceful degradation.
|
|
692
|
+
*
|
|
693
|
+
* @param sha - The 40-character SHA-1 hash of the object to read
|
|
694
|
+
* @returns Promise resolving to the read result with object, tier, and metrics
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```typescript
|
|
698
|
+
* const result = await reader.read('a1b2c3d4e5f678901234567890abcdef12345678')
|
|
699
|
+
*
|
|
700
|
+
* if (result.object) {
|
|
701
|
+
* // Object found
|
|
702
|
+
* console.log(`Type: ${result.object.type}`)
|
|
703
|
+
* console.log(`Tier: ${result.tier}`)
|
|
704
|
+
* console.log(`Promoted: ${result.promoted}`)
|
|
705
|
+
* } else {
|
|
706
|
+
* // Object not found
|
|
707
|
+
* console.log(`Search took ${result.latencyMs}ms`)
|
|
708
|
+
* }
|
|
709
|
+
* ```
|
|
108
710
|
*/
|
|
109
711
|
read(sha: string): Promise<ReadResult>;
|
|
110
712
|
/**
|
|
111
|
-
*
|
|
713
|
+
* Reads an object directly from the hot tier only.
|
|
714
|
+
*
|
|
715
|
+
* @description
|
|
716
|
+
* Bypasses the tier fallback logic to read directly from the hot tier.
|
|
717
|
+
* Useful for checking if an object is already in the hot cache.
|
|
718
|
+
* Errors are caught and null is returned.
|
|
719
|
+
*
|
|
720
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
721
|
+
* @returns Promise resolving to the object or null if not in hot tier
|
|
722
|
+
*
|
|
723
|
+
* @example
|
|
724
|
+
* ```typescript
|
|
725
|
+
* const cached = await reader.readFromHot(sha)
|
|
726
|
+
* if (cached) {
|
|
727
|
+
* console.log('Object is in hot cache')
|
|
728
|
+
* } else {
|
|
729
|
+
* console.log('Object not in hot cache')
|
|
730
|
+
* }
|
|
731
|
+
* ```
|
|
112
732
|
*/
|
|
113
733
|
readFromHot(sha: string): Promise<StoredObject | null>;
|
|
114
734
|
/**
|
|
115
|
-
*
|
|
735
|
+
* Reads an object directly from the warm tier only.
|
|
736
|
+
*
|
|
737
|
+
* @description
|
|
738
|
+
* Bypasses the tier fallback logic to read directly from the warm tier.
|
|
739
|
+
* Does not trigger automatic promotion to hot tier.
|
|
740
|
+
* Errors are caught and null is returned.
|
|
741
|
+
*
|
|
742
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
743
|
+
* @returns Promise resolving to the object or null if not in warm tier
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* const warm = await reader.readFromWarm(sha)
|
|
748
|
+
* if (warm) {
|
|
749
|
+
* // Manually promote if desired
|
|
750
|
+
* await reader.promoteToHot(sha, warm)
|
|
751
|
+
* }
|
|
752
|
+
* ```
|
|
116
753
|
*/
|
|
117
754
|
readFromWarm(sha: string): Promise<StoredObject | null>;
|
|
118
755
|
/**
|
|
119
|
-
*
|
|
756
|
+
* Reads an object directly from the cold tier only.
|
|
757
|
+
*
|
|
758
|
+
* @description
|
|
759
|
+
* Bypasses the tier fallback logic to read directly from the cold tier.
|
|
760
|
+
* Does not trigger automatic promotion to hotter tiers.
|
|
761
|
+
* Errors are caught and null is returned.
|
|
762
|
+
*
|
|
763
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
764
|
+
* @returns Promise resolving to the object or null if not in cold tier
|
|
765
|
+
*
|
|
766
|
+
* @example
|
|
767
|
+
* ```typescript
|
|
768
|
+
* const cold = await reader.readFromCold(sha)
|
|
769
|
+
* if (cold) {
|
|
770
|
+
* console.log(`Found in cold storage, created at: ${cold.createdAt}`)
|
|
771
|
+
* }
|
|
772
|
+
* ```
|
|
120
773
|
*/
|
|
121
774
|
readFromCold(sha: string): Promise<StoredObject | null>;
|
|
122
775
|
/**
|
|
123
|
-
* Manually
|
|
776
|
+
* Manually promotes an object to the hot tier.
|
|
777
|
+
*
|
|
778
|
+
* @description
|
|
779
|
+
* Copies the provided object to the hot tier storage. This is useful for
|
|
780
|
+
* pre-warming the cache or manually controlling tier placement. No size
|
|
781
|
+
* or policy checks are performed - the object is always written.
|
|
782
|
+
*
|
|
783
|
+
* @param sha - The 40-character SHA-1 hash of the object
|
|
784
|
+
* @param object - The complete stored object to promote
|
|
785
|
+
* @returns Promise that resolves when promotion is complete
|
|
786
|
+
* @throws Error if the hot tier write fails
|
|
787
|
+
*
|
|
788
|
+
* @example
|
|
789
|
+
* ```typescript
|
|
790
|
+
* // Pre-warm the hot cache
|
|
791
|
+
* const objects = await reader.query({ type: 'commit' })
|
|
792
|
+
* for (const obj of objects) {
|
|
793
|
+
* await reader.promoteToHot(obj.sha, obj)
|
|
794
|
+
* }
|
|
795
|
+
* ```
|
|
124
796
|
*/
|
|
125
797
|
promoteToHot(sha: string, object: StoredObject): Promise<void>;
|
|
126
798
|
/**
|
|
127
|
-
*
|
|
799
|
+
* Returns the current storage configuration.
|
|
800
|
+
*
|
|
801
|
+
* @description
|
|
802
|
+
* Returns the configuration object passed to the constructor.
|
|
803
|
+
* Useful for inspecting current settings or debugging.
|
|
804
|
+
*
|
|
805
|
+
* @returns The tiered storage configuration
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* const config = reader.getConfig()
|
|
810
|
+
* console.log(`Promotion policy: ${config.promotionPolicy}`)
|
|
811
|
+
* console.log(`Hot tier enabled: ${config.hot.enabled}`)
|
|
812
|
+
* ```
|
|
128
813
|
*/
|
|
129
814
|
getConfig(): TieredStorageConfig;
|
|
130
815
|
/**
|
|
131
|
-
*
|
|
816
|
+
* Attempts to promote an object to the hot tier based on policy.
|
|
817
|
+
*
|
|
818
|
+
* @description
|
|
819
|
+
* Called internally when an object is found in warm or cold tier.
|
|
820
|
+
* Decides whether to promote based on:
|
|
821
|
+
* 1. Hot tier being enabled
|
|
822
|
+
* 2. Promotion policy (aggressive promotes, conservative/none don't)
|
|
823
|
+
* 3. Object size being within hot tier's maxSize limit
|
|
824
|
+
*
|
|
825
|
+
* @param sha - The object's SHA-1 hash
|
|
826
|
+
* @param object - The object to potentially promote
|
|
827
|
+
* @param _sourceTier - The tier the object was read from (for future use)
|
|
828
|
+
* @returns true if promotion was successful, false otherwise
|
|
132
829
|
*
|
|
133
|
-
* @
|
|
134
|
-
* @param object - The object to promote
|
|
135
|
-
* @param sourceTier - The tier the object was read from
|
|
136
|
-
* @returns true if promotion was successful
|
|
830
|
+
* @private
|
|
137
831
|
*/
|
|
138
832
|
private tryPromote;
|
|
139
833
|
}
|