Skip to content

Commit e00aa94

Browse files
authored
refactor!: Align DatasetClient and KeyValueStoreClient interfaces with their Python counterparts (#3627)
closes #3075
1 parent 99d4cc9 commit e00aa94

29 files changed

Lines changed: 840 additions & 1822 deletions

docs/upgrading/upgrading_v4.md

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,61 @@ The `StorageClient` interface changed from synchronous sub-client getters to **a
465465
| `client.requestQueue(id, opts)` | `client.createRequestQueueClient({ id?, name?, clientKey?, timeoutSecs? })` |
466466
| `client.requestQueues().getOrCreate(name)` | _(absorbed into `createRequestQueueClient`)_ |
467467

468-
The `get()` method on `DatasetClient`, `KeyValueStoreClient`, and `RequestQueueClient` has been renamed to **`getMetadata()`**.
468+
The sub-client interfaces (`DatasetClient`, `KeyValueStoreClient`, `RequestQueueClient`) have been aligned with their Python counterparts:
469+
470+
| Before (v3) | After (v4) |
471+
|---|---|
472+
| `get()` | `getMetadata()` |
473+
| `update()` | Removed |
474+
| `delete()` | `drop()` |
475+
| _(n/a)_ | `purge()` (new — clears data, keeps storage) |
476+
477+
**`DatasetClient`:**
478+
479+
| Before (v3) | After (v4) |
480+
|---|---|
481+
| `pushItems(items: Data \| Data[] \| string \| string[])` | `pushData(items: Data[])` |
482+
| `listItems(options?)` (dual iterable) | `getData(options?)` (returns a single `PaginatedList` page) |
483+
| `listEntries(options?)` | Removed (handled by `Dataset` frontend) |
484+
| `downloadItems()` | Removed |
485+
486+
**`KeyValueStoreClient`:**
487+
488+
| Before (v3) | After (v4) |
489+
|---|---|
490+
| `getRecord(key, options?)` | `getValue(key)` |
491+
| `setRecord(record, options?)` | `setValue(record)` |
492+
| `deleteRecord(key)` | `deleteValue(key)` |
493+
| `getRecordPublicUrl(key)` | `getPublicUrl(key)` |
494+
| `listKeys(options?)``KeyValueStoreClientListData` | `listKeys(options?)``KeyValueStoreItemData[]` |
495+
| `keys()`, `values()`, `entries()` | Removed (handled by `KeyValueStore` frontend) |
496+
497+
**`RequestQueueClient`:**
498+
499+
| Before (v3) | After (v4) |
500+
|---|---|
501+
| `deleteRequest(id)` | Removed |
502+
503+
**Removed types** from `@crawlee/types`: `DatasetClientUpdateOptions`, `KeyValueStoreClientUpdateOptions`, `KeyValueStoreRecordOptions`, `KeyValueStoreClientListData`, `KeyValueStoreClientGetRecordOptions`. `KeyValueStoreClientListOptions` was renamed to `KeyValueStoreListKeysOptions`.
469504

470505
The high-level storage classes (`Dataset`, `KeyValueStore`, `RequestQueue`) now receive their sub-client directly in the constructor options instead of receiving a `StorageClient` and calling its methods.
471506

507+
### `RecordOptions` simplified
508+
509+
`timeoutSecs` and `doNotRetryTimeouts` were removed from `RecordOptions` (used by `KeyValueStore.setValue`). Only `contentType` remains.
510+
511+
### `KeyValueStoreIteratorOptions` simplified
512+
513+
`exclusiveStartKey` and `collection` were removed. Only `prefix` remains.
514+
515+
### `Dataset.listItems` replaced by `Dataset.getData` and `Dataset.values`
516+
517+
`Dataset.listItems()` is replaced by two methods:
518+
- `Dataset.getData(options?)` — returns a single `PaginatedList<Data>` page.
519+
- `Dataset.values(options?)` — dual iterable: `for await...of` iterates all items; `await` returns all items as `Data[]`.
520+
521+
`Dataset.entries()` works the same way as `values()` but yields `[index, Data]` tuples. `KeyValueStore.keys()`, `.values()`, `.entries()` follow the same dual-iterable pattern.
522+
472523
### Removed `list()` method
473524

474525
The `list()` method on collection clients (e.g. `client.datasets().list()`) has no replacement. If you were using it to enumerate all storages, you will need to use the Apify API client directly.
@@ -479,7 +530,7 @@ If you implemented a custom `StorageClient`, you need to:
479530

480531
1. Remove your `*CollectionClient` classes.
481532
2. Replace the six getter methods (`dataset`, `datasets`, `keyValueStore`, `keyValueStores`, `requestQueue`, `requestQueues`) with three async factory methods (`createDatasetClient`, `createKeyValueStoreClient`, `createRequestQueueClient`). Each factory should handle both opening an existing storage and creating a new one.
482-
3. Rename `get()` to `getMetadata()` on your `DatasetClient`, `KeyValueStoreClient`, and `RequestQueueClient` implementations.
533+
3. Apply the sub-client renames listed above (`get` `getMetadata`, `delete``drop`, etc.) and implement the new `purge()` method.
483534

484535
## Storage `.open()` now also accepts `{ id?, name? }`
485536

packages/core/src/crawlers/statistics.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -330,14 +330,8 @@ export class Statistics {
330330

331331
this.log.debug('Persisting state', { persistStateKey: this.persistStateKey });
332332

333-
// use half the interval of `persistState` to avoid race conditions
334-
const persistStateIntervalMillis = serviceLocator.getConfiguration().persistStateIntervalMillis;
335-
const timeoutSecs = persistStateIntervalMillis / 2_000;
336333
await this.keyValueStore
337-
.setValue(this.persistStateKey, this.toJSON(), {
338-
timeoutSecs,
339-
doNotRetryTimeouts: true,
340-
})
334+
.setValue(this.persistStateKey, this.toJSON())
341335
.catch((error) =>
342336
this.log.warning(`Failed to persist the statistics to ${this.persistStateKey}`, { error }),
343337
);

packages/core/src/session_pool/session_pool.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -371,14 +371,8 @@ export class SessionPool implements ISessionPool {
371371
persistStateKey: this.persistStateKey,
372372
});
373373

374-
// use half the interval of `persistState` to avoid race conditions
375-
const persistStateIntervalMillis = serviceLocator.getConfiguration().persistStateIntervalMillis;
376-
const timeoutSecs = persistStateIntervalMillis / 2_000;
377374
await this.keyValueStore
378-
?.setValue(this.persistStateKey, await this.getState(), {
379-
timeoutSecs,
380-
doNotRetryTimeouts: true,
381-
})
375+
?.setValue(this.persistStateKey, await this.getState())
382376
.catch((error) =>
383377
this.log.warning(`Failed to persist the session pool stats to ${this.persistStateKey}`, { error }),
384378
);

0 commit comments

Comments
 (0)