@crawlee/core 4.0.0-beta.99 → 4.0.0-rc.1

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.
Files changed (133) hide show
  1. package/README.md +1 -1
  2. package/configuration.d.ts +16 -47
  3. package/configuration.js +13 -25
  4. package/debug.js +4 -4
  5. package/errors.d.ts +28 -38
  6. package/errors.js +33 -47
  7. package/events/event_manager.d.ts +2 -2
  8. package/events/event_manager.js +7 -6
  9. package/events/index.d.ts +1 -0
  10. package/events/local_event_manager.d.ts +1 -8
  11. package/events/local_event_manager.js +13 -13
  12. package/events/system_info.d.ts +38 -0
  13. package/index.d.ts +2 -8
  14. package/index.js +4 -8
  15. package/internal.d.ts +8 -0
  16. package/internal.js +9 -0
  17. package/log.d.ts +10 -11
  18. package/log.js +52 -20
  19. package/memory-storage/memory-storage.d.ts +15 -18
  20. package/memory-storage/memory-storage.js +80 -58
  21. package/memory-storage/resource-clients/dataset.d.ts +1 -6
  22. package/memory-storage/resource-clients/dataset.js +23 -31
  23. package/memory-storage/resource-clients/key-value-store.d.ts +1 -10
  24. package/memory-storage/resource-clients/key-value-store.js +43 -67
  25. package/memory-storage/resource-clients/request-queue.d.ts +1 -42
  26. package/memory-storage/resource-clients/request-queue.js +109 -117
  27. package/owned_or_injected.d.ts +1 -3
  28. package/owned_or_injected.js +17 -17
  29. package/package.json +17 -20
  30. package/proxy_configuration.d.ts +21 -26
  31. package/proxy_configuration.js +35 -25
  32. package/recoverable_state.d.ts +104 -47
  33. package/recoverable_state.js +199 -74
  34. package/request.d.ts +20 -107
  35. package/request.js +78 -244
  36. package/serialization.js +17 -16
  37. package/service_locator.d.ts +22 -10
  38. package/service_locator.js +59 -48
  39. package/storages/batched_adds.d.ts +37 -0
  40. package/storages/batched_adds.js +73 -0
  41. package/storages/dataset.d.ts +13 -8
  42. package/storages/dataset.js +149 -40
  43. package/storages/index.d.ts +4 -4
  44. package/storages/index.js +2 -4
  45. package/storages/key_value_store.d.ts +16 -35
  46. package/storages/key_value_store.js +223 -110
  47. package/storages/key_value_store_codec.js +6 -11
  48. package/storages/request_dedup_cache.d.ts +1 -4
  49. package/storages/request_dedup_cache.js +15 -15
  50. package/storages/request_list.d.ts +9 -104
  51. package/storages/request_list.js +236 -233
  52. package/storages/request_loader.d.ts +49 -18
  53. package/storages/request_loader.js +36 -1
  54. package/storages/request_manager.d.ts +86 -0
  55. package/storages/request_manager_tandem.d.ts +14 -38
  56. package/storages/request_manager_tandem.js +67 -64
  57. package/storages/request_queue.d.ts +23 -50
  58. package/storages/request_queue.js +371 -226
  59. package/storages/storage_instance_manager.d.ts +2 -4
  60. package/storages/storage_instance_manager.js +21 -21
  61. package/storages/storage_stats.d.ts +1 -1
  62. package/storages/storage_stats.js +4 -4
  63. package/storages/transaction.d.ts +270 -0
  64. package/storages/transaction.js +296 -0
  65. package/storages/utils.d.ts +6 -3
  66. package/storages/utils.js +11 -2
  67. package/system-info/runtime.js +7 -7
  68. package/url.d.ts +9 -0
  69. package/url.js +11 -0
  70. package/validators.d.ts +23 -25
  71. package/validators.js +14 -25
  72. package/autoscaling/autoscaled_pool.d.ts +0 -213
  73. package/autoscaling/autoscaled_pool.js +0 -378
  74. package/autoscaling/client_load_signal.d.ts +0 -59
  75. package/autoscaling/client_load_signal.js +0 -73
  76. package/autoscaling/concurrency_system.d.ts +0 -283
  77. package/autoscaling/concurrency_system.js +0 -350
  78. package/autoscaling/cpu_load_signal.d.ts +0 -44
  79. package/autoscaling/cpu_load_signal.js +0 -46
  80. package/autoscaling/event_loop_load_signal.d.ts +0 -54
  81. package/autoscaling/event_loop_load_signal.js +0 -60
  82. package/autoscaling/index.d.ts +0 -9
  83. package/autoscaling/index.js +0 -9
  84. package/autoscaling/load_signal.d.ts +0 -99
  85. package/autoscaling/load_signal.js +0 -103
  86. package/autoscaling/memory_load_signal.d.ts +0 -56
  87. package/autoscaling/memory_load_signal.js +0 -106
  88. package/autoscaling/snapshotter.d.ts +0 -87
  89. package/autoscaling/snapshotter.js +0 -67
  90. package/autoscaling/system_status.d.ts +0 -161
  91. package/autoscaling/system_status.js +0 -139
  92. package/autoscaling/weighted_avg.d.ts +0 -5
  93. package/autoscaling/weighted_avg.js +0 -14
  94. package/cookie_utils.d.ts +0 -44
  95. package/cookie_utils.js +0 -122
  96. package/crawlers/context_pipeline.d.ts +0 -70
  97. package/crawlers/context_pipeline.js +0 -122
  98. package/crawlers/crawler_commons.d.ts +0 -257
  99. package/crawlers/crawler_commons.js +0 -107
  100. package/crawlers/error_snapshotter.d.ts +0 -59
  101. package/crawlers/error_snapshotter.js +0 -117
  102. package/crawlers/error_tracker.d.ts +0 -54
  103. package/crawlers/error_tracker.js +0 -308
  104. package/crawlers/index.d.ts +0 -5
  105. package/crawlers/index.js +0 -5
  106. package/crawlers/internals/types.d.ts +0 -7
  107. package/crawlers/statistics.d.ts +0 -209
  108. package/crawlers/statistics.js +0 -350
  109. package/enqueue_links/enqueue_links.d.ts +0 -264
  110. package/enqueue_links/enqueue_links.js +0 -271
  111. package/enqueue_links/index.d.ts +0 -2
  112. package/enqueue_links/index.js +0 -2
  113. package/enqueue_links/shared.d.ts +0 -83
  114. package/enqueue_links/shared.js +0 -221
  115. package/router.d.ts +0 -309
  116. package/router.js +0 -309
  117. package/session_pool/consts.d.ts +0 -3
  118. package/session_pool/consts.js +0 -3
  119. package/session_pool/errors.d.ts +0 -7
  120. package/session_pool/errors.js +0 -11
  121. package/session_pool/fingerprint.d.ts +0 -9
  122. package/session_pool/fingerprint.js +0 -30
  123. package/session_pool/index.d.ts +0 -4
  124. package/session_pool/index.js +0 -4
  125. package/session_pool/session.d.ts +0 -161
  126. package/session_pool/session.js +0 -218
  127. package/session_pool/session_pool.d.ts +0 -246
  128. package/session_pool/session_pool.js +0 -386
  129. package/storages/access_checking.d.ts +0 -12
  130. package/storages/access_checking.js +0 -17
  131. package/storages/sitemap_request_loader.d.ts +0 -249
  132. package/storages/sitemap_request_loader.js +0 -432
  133. /package/{crawlers/internals/types.js → events/system_info.js} +0 -0
@@ -7,7 +7,6 @@ export interface IStorage {
7
7
  id: string;
8
8
  name?: string;
9
9
  }
10
- type Hashable = string;
11
10
  /**
12
11
  * Unified manager for opening and caching storage instances (Dataset, KeyValueStore, RequestQueue).
13
12
  *
@@ -19,8 +18,7 @@ type Hashable = string;
19
18
  * assigns a reserved default alias.
20
19
  */
21
20
  export declare class StorageInstanceManager {
22
- private readonly cache;
23
- private readonly openerLocks;
21
+ #private;
24
22
  /**
25
23
  * Open (or retrieve from cache) a storage instance.
26
24
  *
@@ -36,7 +34,7 @@ export declare class StorageInstanceManager {
36
34
  */
37
35
  openStorage<TStorage extends IStorage>(cls: Constructor<TStorage>, { id, name, alias, backendOpener, backendCacheKey, }: (ExplicitStorageIdentifier | DefaultStorageIdentifier) & {
38
36
  backendOpener: () => Promise<DatasetBackend | KeyValueStoreBackend | RequestQueueBackend>;
39
- backendCacheKey: Hashable;
37
+ backendCacheKey: string;
40
38
  }): Promise<TStorage>;
41
39
  /**
42
40
  * Remove a storage instance from the cache (called from `storage.drop()`).
@@ -32,7 +32,7 @@ class StorageCache {
32
32
  return undefined;
33
33
  }
34
34
  /** Write a single entry into a given tier. */
35
- setInMap(tier, cls, key, instance, backendCacheKey) {
35
+ #setInMap(tier, cls, key, instance, backendCacheKey) {
36
36
  if (!tier.has(cls))
37
37
  tier.set(cls, new Map());
38
38
  const keyMap = tier.get(cls);
@@ -45,14 +45,14 @@ class StorageCache {
45
45
  */
46
46
  set(cls, instance, backendCacheKey, alias) {
47
47
  // Always cache by id.
48
- this.setInMap(this.byId, cls, instance.id, instance, backendCacheKey);
48
+ this.#setInMap(this.byId, cls, instance.id, instance, backendCacheKey);
49
49
  // Cache by name — only for named storages.
50
50
  if (instance.name) {
51
- this.setInMap(this.byName, cls, instance.name, instance, backendCacheKey);
51
+ this.#setInMap(this.byName, cls, instance.name, instance, backendCacheKey);
52
52
  }
53
53
  // Cache by alias — only for unnamed storages opened via alias.
54
54
  if (alias !== undefined) {
55
- this.setInMap(this.byAlias, cls, alias, instance, backendCacheKey);
55
+ this.#setInMap(this.byAlias, cls, alias, instance, backendCacheKey);
56
56
  }
57
57
  }
58
58
  removeFromCache(instance) {
@@ -120,8 +120,8 @@ class StorageCache {
120
120
  * assigns a reserved default alias.
121
121
  */
122
122
  export class StorageInstanceManager {
123
- cache = new StorageCache();
124
- openerLocks = new Map();
123
+ #cache = new StorageCache();
124
+ #openerLocks = new Map();
125
125
  /**
126
126
  * Open (or retrieve from cache) a storage instance.
127
127
  *
@@ -142,46 +142,46 @@ export class StorageInstanceManager {
142
142
  }
143
143
  // Fast-path cache check (no lock).
144
144
  if (alias !== undefined) {
145
- const cached = this.cache.get(cls, { alias, backendCacheKey });
145
+ const cached = this.#cache.get(cls, { alias, backendCacheKey });
146
146
  if (cached)
147
147
  return cached;
148
148
  }
149
149
  else if (id) {
150
- const cached = this.cache.get(cls, { id, backendCacheKey });
150
+ const cached = this.#cache.get(cls, { id, backendCacheKey });
151
151
  if (cached)
152
152
  return cached;
153
153
  }
154
154
  else if (name) {
155
- const cached = this.cache.get(cls, { name, backendCacheKey });
155
+ const cached = this.#cache.get(cls, { name, backendCacheKey });
156
156
  if (cached)
157
157
  return cached;
158
158
  }
159
159
  const identifierKey = id ?? name ?? alias ?? DEFAULT_STORAGE_ALIAS;
160
160
  const lockKey = `${cls.name}:${identifierKey}:${backendCacheKey}`;
161
- if (!this.openerLocks.has(lockKey)) {
162
- this.openerLocks.set(lockKey, new AsyncQueue());
161
+ if (!this.#openerLocks.has(lockKey)) {
162
+ this.#openerLocks.set(lockKey, new AsyncQueue());
163
163
  }
164
- const queue = this.openerLocks.get(lockKey);
164
+ const queue = this.#openerLocks.get(lockKey);
165
165
  await queue.wait();
166
166
  try {
167
167
  // Double-check cache under lock (another caller may have filled it while we waited).
168
168
  if (alias !== undefined) {
169
- const cached = this.cache.get(cls, { alias, backendCacheKey });
169
+ const cached = this.#cache.get(cls, { alias, backendCacheKey });
170
170
  if (cached)
171
171
  return cached;
172
172
  }
173
173
  else if (id) {
174
- const cached = this.cache.get(cls, { id, backendCacheKey });
174
+ const cached = this.#cache.get(cls, { id, backendCacheKey });
175
175
  if (cached)
176
176
  return cached;
177
177
  }
178
178
  else if (name) {
179
- const cached = this.cache.get(cls, { name, backendCacheKey });
179
+ const cached = this.#cache.get(cls, { name, backendCacheKey });
180
180
  if (cached)
181
181
  return cached;
182
182
  }
183
183
  // Prevent the same string from being used as both a name and an alias.
184
- this.cache.checkNameAliasConflict(cls, { name, alias, backendCacheKey });
184
+ this.#cache.checkNameAliasConflict(cls, { name, alias, backendCacheKey });
185
185
  // Cache miss — create the sub-backend and storage instance.
186
186
  const subBackend = await backendOpener();
187
187
  const storageInfo = await subBackend.getMetadata();
@@ -189,7 +189,7 @@ export class StorageInstanceManager {
189
189
  // we just fetched (so `id`/`name` etc. are available synchronously) along with the backend.
190
190
  const instance = new cls({ metadata: storageInfo, backend: subBackend });
191
191
  // Atomic cache writes (no awaits between these).
192
- this.cache.set(cls, instance, backendCacheKey, alias);
192
+ this.#cache.set(cls, instance, backendCacheKey, alias);
193
193
  return instance;
194
194
  }
195
195
  finally {
@@ -197,7 +197,7 @@ export class StorageInstanceManager {
197
197
  // Clean up idle locks so the map doesn't grow unboundedly
198
198
  // (mirrors crawlee-python's WeakValueDictionary behaviour).
199
199
  if (queue.remaining === 0) {
200
- this.openerLocks.delete(lockKey);
200
+ this.#openerLocks.delete(lockKey);
201
201
  }
202
202
  }
203
203
  }
@@ -205,7 +205,7 @@ export class StorageInstanceManager {
205
205
  * Remove a storage instance from the cache (called from `storage.drop()`).
206
206
  */
207
207
  removeFromCache(instance) {
208
- this.cache.removeFromCache(instance);
208
+ this.#cache.removeFromCache(instance);
209
209
  }
210
210
  /**
211
211
  * Clear the entire cache. Also calls `clearCache()` on any cached KeyValueStore
@@ -213,12 +213,12 @@ export class StorageInstanceManager {
213
213
  * Called during service locator reset.
214
214
  */
215
215
  clearCache() {
216
- for (const instance of this.cache.allValues()) {
216
+ for (const instance of this.#cache.allValues()) {
217
217
  if ('clearCache' in instance && typeof instance.clearCache === 'function') {
218
218
  instance.clearCache();
219
219
  }
220
220
  }
221
- this.cache.clear();
221
+ this.#cache.clear();
222
222
  }
223
223
  }
224
224
  /**
@@ -39,7 +39,7 @@ export interface RequestQueueStats {
39
39
  * the buckets that make sense for it.
40
40
  */
41
41
  export declare class StorageStatsTracker<T extends Record<keyof T, number>> {
42
- private readonly counters;
42
+ #private;
43
43
  constructor(initial: T);
44
44
  /** Increment a counter bucket by `by` (default `1`). */
45
45
  add(key: keyof T, by?: number): void;
@@ -14,16 +14,16 @@
14
14
  * the buckets that make sense for it.
15
15
  */
16
16
  export class StorageStatsTracker {
17
- counters;
17
+ #counters;
18
18
  constructor(initial) {
19
- this.counters = { ...initial };
19
+ this.#counters = { ...initial };
20
20
  }
21
21
  /** Increment a counter bucket by `by` (default `1`). */
22
22
  add(key, by = 1) {
23
- this.counters[key] += by;
23
+ this.#counters[key] += by;
24
24
  }
25
25
  /** Return a snapshot of the current counters. The returned object is a copy and safe to keep. */
26
26
  get current() {
27
- return { ...this.counters };
27
+ return { ...this.#counters };
28
28
  }
29
29
  }
@@ -0,0 +1,270 @@
1
+ import type { Awaitable, Dictionary, RequestSchema } from '@crawlee/types';
2
+ import type { RecordOptions } from './key_value_store.js';
3
+ /**
4
+ * Governs whether writes of a given storage type performed inside a {@link StorageTransaction} are
5
+ * applied immediately (`writeThrough`) or recorded and replayed on commit (`deferred`).
6
+ */
7
+ export type StorageWriteMode = 'deferred' | 'writeThrough';
8
+ /**
9
+ * Per-storage-type write policy of a {@link StorageTransaction}. Datasets and key-value stores are
10
+ * always `deferred` and not configurable — deferring is the only safe mode for non-idempotent writes,
11
+ * and {@link withDirectStorageAccess} covers one-off immediate writes.
12
+ */
13
+ export interface StorageWritePolicy {
14
+ /**
15
+ * Write mode for request queue additions. Note that this is a *write policy* for the queue, not the
16
+ * queue instance itself (which is the top-level `requestQueue` crawler option).
17
+ *
18
+ * - `writeThrough` (default): requests are added immediately and are **not** rolled back with the
19
+ * transaction. This is safe (additions are deduplicated by `uniqueKey`, so a retry is idempotent)
20
+ * and keeps new requests visible to the crawler while the handler still runs.
21
+ * - `deferred`: requests are only added when the transaction commits — strict all-or-nothing
22
+ * semantics, at the cost of the crawler not seeing them until the handler finishes.
23
+ */
24
+ requestQueue: StorageWriteMode;
25
+ }
26
+ export type StorageTransactionState = 'open' | 'committing' | 'committed' | 'failed' | 'rolledBack';
27
+ /**
28
+ * A storage frontend that can record operations in a transaction journal.
29
+ * @internal
30
+ */
31
+ export interface TransactionParticipant {
32
+ /**
33
+ * Replay the given buffered journal entries (all recorded by this participant) into the real storage
34
+ * backend. Called during commit, with the transaction already in the `committing` state, so the
35
+ * replayed operations pass through.
36
+ */
37
+ commitJournalEntries(entries: JournalEntry[]): Promise<void>;
38
+ }
39
+ /**
40
+ * A single dataset write (`pushData`) recorded in a transaction journal.
41
+ * @internal
42
+ */
43
+ export interface DatasetJournalEntry {
44
+ type: 'dataset';
45
+ /** @internal **/
46
+ participant: TransactionParticipant;
47
+ storageId: string;
48
+ /** The pushed items, captured by `structuredClone` at write time. */
49
+ items: Dictionary[];
50
+ recordedAt: Date;
51
+ }
52
+ /**
53
+ * A single key-value store write (`setValue`) recorded in a transaction journal.
54
+ * @internal
55
+ */
56
+ export interface KeyValueStoreJournalEntry {
57
+ type: 'keyValueStore';
58
+ /** @internal **/
59
+ participant: TransactionParticipant;
60
+ storageId: string;
61
+ key: string;
62
+ /** The original, pre-serialization value captured by `structuredClone`; `null` denotes a deletion. */
63
+ value: unknown;
64
+ options?: RecordOptions;
65
+ }
66
+ /**
67
+ * A request recorded in a transaction journal.
68
+ * @internal
69
+ */
70
+ export interface JournaledRequest {
71
+ url: string;
72
+ uniqueKey: string;
73
+ label?: string;
74
+ /**
75
+ * A full JSON snapshot of the request for the commit replay. Only present for buffered additions —
76
+ * deduplicated and write-through ones are journaled for introspection only.
77
+ */
78
+ snapshot?: RequestSchema;
79
+ }
80
+ /**
81
+ * A batch of request queue additions recorded in a transaction journal.
82
+ * @internal
83
+ */
84
+ export interface RequestQueueJournalEntry {
85
+ type: 'requestQueue';
86
+ /** @internal **/
87
+ participant: TransactionParticipant;
88
+ requests: JournaledRequest[];
89
+ forefront: boolean;
90
+ /** Write-through entries were applied immediately; they are never replayed. */
91
+ writeThrough: boolean;
92
+ }
93
+ /** @internal */
94
+ export type JournalEntry = DatasetJournalEntry | KeyValueStoreJournalEntry | RequestQueueJournalEntry;
95
+ /**
96
+ * A read-only view of a {@link StorageTransaction}: only the journal-backed introspection accessors,
97
+ * without the lifecycle methods. The accessors are synchronous and expose the original pre-serialization
98
+ * values. They cover every write recorded while the transaction was open, under either write policy —
99
+ * with the one exception noted on {@link StorageTransactionView.enqueuedUrls|`enqueuedUrls`}. A view
100
+ * is valid until the transaction is disposed.
101
+ */
102
+ export interface StorageTransactionView {
103
+ readonly state: StorageTransactionState;
104
+ /** Items pushed to datasets during the transaction, in push order. */
105
+ readonly datasetItems: {
106
+ item: Dictionary;
107
+ datasetId: string;
108
+ }[];
109
+ /**
110
+ * URLs enqueued to request queues during the transaction, under either write policy. Recorded as
111
+ * requested, so duplicate, already-present and backend-rejected URLs are included.
112
+ *
113
+ * One gap: unless a caller of `addRequestsBatched()` waits for every chunk
114
+ * (`waitForAllRequestsToBeAdded` or `maxNewRequests`, both of which {@link enqueueLinks} sets when
115
+ * a crawl limit applies), the chunks after the first are added by a background writer that outlives
116
+ * the transaction and is not recorded here.
117
+ */
118
+ readonly enqueuedUrls: {
119
+ url: string;
120
+ label?: string;
121
+ }[];
122
+ /** Key-value store changes made during the transaction, keyed by store id, last write per key. */
123
+ readonly keyValueStoreChanges: Record<string, Record<string, {
124
+ changedValue: unknown;
125
+ options?: RecordOptions;
126
+ }>>;
127
+ }
128
+ export interface StorageTransactionOptions {
129
+ /** Overrides of the per-storage-type write policy. See {@link StorageWritePolicy}. */
130
+ policy?: Partial<StorageWritePolicy>;
131
+ /**
132
+ * How long a commit may take before it fails, in milliseconds. There is no automatic retry — the
133
+ * replay of dataset items is not idempotent.
134
+ * @default 300000
135
+ */
136
+ commitTimeoutMillis?: number;
137
+ }
138
+ /**
139
+ * A storage transaction scoped to a request's lifecycle. Writes made through the storage frontends
140
+ * ({@link Dataset}, {@link KeyValueStore}, {@link RequestQueue}) while the transaction is active
141
+ * are recorded rather than applied; on {@link StorageTransaction.commit|`commit()`} they are replayed
142
+ * into real storage, on {@link StorageTransaction.rollback|`rollback()`} they are dropped. Reads consult
143
+ * the recorded writes first, so a handler sees its own writes.
144
+ *
145
+ * Create one with {@link createStorageTransaction} (explicit commit/rollback) or
146
+ * {@link withStorageTransaction} (scoped sugar). Crawlers open one automatically around every request
147
+ * handler unless `transactionalStorage: false` is set.
148
+ */
149
+ export declare class StorageTransaction implements StorageTransactionView {
150
+ #private;
151
+ /**
152
+ * The ordered, append-only journal — the source of truth for commit, introspection and reads.
153
+ * @internal
154
+ */
155
+ readonly journal: JournalEntry[];
156
+ /** @internal */
157
+ constructor(options?: StorageTransactionOptions);
158
+ /**
159
+ * Per-storage-type write policy.
160
+ * @internal
161
+ */
162
+ get policy(): StorageWritePolicy;
163
+ get state(): StorageTransactionState;
164
+ /**
165
+ * `true` only while `state === 'open'`. This is the single predicate every storage operation
166
+ * consults — operations performed after the transaction is closed pass through to the real backend.
167
+ */
168
+ get isActive(): boolean;
169
+ /** Runs `callback` with this transaction installed in the async context. */
170
+ run<T>(callback: () => Awaitable<T>): Promise<T>;
171
+ /**
172
+ * Records a write operation in the journal.
173
+ * @internal
174
+ */
175
+ recordJournalEntry(entry: JournalEntry): void;
176
+ /**
177
+ * Registers a callback to run once a commit has been attempted, whether it succeeded (`error` is
178
+ * `undefined`) or failed - the only point at which a deferred write can be reacted to where it was
179
+ * made. Callbacks run in registration order; the first to throw propagates, the rest do not run, and
180
+ * on a failed commit its error replaces the commit error. Not run on rollback: nothing was written.
181
+ */
182
+ afterCommit(callback: (error?: Error) => Awaitable<void>): void;
183
+ /**
184
+ * Replays the journaled writes into real storage. A no-op unless the transaction is `open`.
185
+ *
186
+ * The transaction transitions to `committing` *before* anything is flushed, so a commit that throws
187
+ * partway lands in `failed` (never back in `open`) and subsequent storage operations pass through
188
+ * rather than recording into a dead transaction. Delivery is at-least-once — a commit that fails
189
+ * partway may have applied some of the writes already.
190
+ */
191
+ commit(): Promise<void>;
192
+ /**
193
+ * Discards the journaled writes. A no-op unless the transaction is `open` — in particular, calling it
194
+ * after a successful `commit()` (which the crawler's error handling can legitimately do) does nothing
195
+ * and never throws.
196
+ */
197
+ rollback(): void;
198
+ /**
199
+ * Releases the journal, the write-time snapshots it holds and any registered commit callbacks. Must
200
+ * be called for *every* terminal state, `failed` included. Idempotent, never throws, and does not
201
+ * change `state`. Any {@link StorageTransactionView} of this transaction is only valid until this
202
+ * is called.
203
+ */
204
+ dispose(): void;
205
+ get datasetItems(): {
206
+ item: Dictionary;
207
+ datasetId: string;
208
+ }[];
209
+ get enqueuedUrls(): {
210
+ url: string;
211
+ label?: string;
212
+ }[];
213
+ get keyValueStoreChanges(): Record<string, Record<string, {
214
+ changedValue: unknown;
215
+ options?: RecordOptions;
216
+ }>>;
217
+ }
218
+ /**
219
+ * Opens a {@link StorageTransaction} without running anything yet. The caller owns the outcome:
220
+ * `run()`, then `commit()` or `rollback()`, and always `dispose()` when done. For the common
221
+ * open-run-commit flow, prefer {@link withStorageTransaction}.
222
+ */
223
+ export declare function createStorageTransaction(options?: StorageTransactionOptions): StorageTransaction;
224
+ /**
225
+ * Runs `callback` inside a new {@link StorageTransaction}: storage writes made in the callback are
226
+ * committed when it returns and rolled back when it throws. If a transaction is already active in the
227
+ * current async context, it is reused and its outcome is left to its owner (and `options` are ignored)
228
+ * — there are no nested transaction semantics.
229
+ */
230
+ export declare function withStorageTransaction<T>(callback: (transaction: StorageTransaction) => Awaitable<T>, options?: StorageTransactionOptions): Promise<T>;
231
+ /**
232
+ * Runs `callback` outside of any storage transaction — the per-call-site escape hatch. Storage operations
233
+ * made inside it hit the real backend directly, are not rolled back, and operations that a transaction
234
+ * rejects (`drop`, stream-valued `setValue`, request queue internals, ...) are permitted.
235
+ */
236
+ export declare function withDirectStorageAccess<T>(callback: () => Awaitable<T>): Promise<T>;
237
+ /**
238
+ * The per-operation hook consulted by every storage frontend method: performs the cancellation check
239
+ * that aborts storage operations when the request handler times out, and returns the active storage
240
+ * transaction. Returns `undefined` when there is no transaction in the async context *or* when it is no
241
+ * longer open — operations on a closed transaction deliberately pass through to the real backend.
242
+ * @internal
243
+ */
244
+ export declare function activeStorageTransaction(): StorageTransaction | undefined;
245
+ /**
246
+ * Returns the transaction installed in the current async context, regardless of its state. Used by the
247
+ * crawler to drive the outcome of the transaction it opened.
248
+ * @internal
249
+ */
250
+ export declare function currentStorageTransaction(): StorageTransaction | undefined;
251
+ /**
252
+ * Captures a value at write time, so that later mutations of the caller's object affect neither the
253
+ * read-your-own-writes reads nor the commit replay. `structuredClone` for fidelity (`Date`, `Map`, `Set`,
254
+ * typed arrays, `undefined`); values it cannot handle fall back to the JSON round-trip the storage
255
+ * backends perform anyway.
256
+ * @internal
257
+ */
258
+ export declare function snapshotValue<T>(value: T): T;
259
+ /**
260
+ * The guard for operations that cannot be performed inside a storage transaction: throws when one is
261
+ * active, and performs the per-operation cancellation check either way.
262
+ * @internal
263
+ */
264
+ export declare function rejectOperationInTransaction(operation: string, reason?: string): void;
265
+ /**
266
+ * Builds the "operation not allowed in a transaction" error, for a call site that has already
267
+ * established a transaction is active and so wants to `throw` unconditionally.
268
+ * @internal
269
+ */
270
+ export declare function operationRejectedInTransaction(operation: string, reason?: string): Error;