@powersync/common 1.51.0 → 1.53.0
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/bundle.cjs +510 -1129
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +511 -1116
- package/dist/bundle.mjs.map +1 -1
- package/dist/bundle.node.cjs +508 -1129
- package/dist/bundle.node.cjs.map +1 -1
- package/dist/bundle.node.mjs +509 -1116
- package/dist/bundle.node.mjs.map +1 -1
- package/dist/index.d.cts +73 -433
- package/legacy/sync_protocol.d.ts +103 -0
- package/lib/client/AbstractPowerSyncDatabase.js +3 -3
- package/lib/client/AbstractPowerSyncDatabase.js.map +1 -1
- package/lib/client/ConnectionManager.js +1 -1
- package/lib/client/ConnectionManager.js.map +1 -1
- package/lib/client/sync/bucket/BucketStorageAdapter.d.ts +6 -64
- package/lib/client/sync/bucket/BucketStorageAdapter.js +4 -0
- package/lib/client/sync/bucket/BucketStorageAdapter.js.map +1 -1
- package/lib/client/sync/bucket/SqliteBucketStorage.d.ts +1 -28
- package/lib/client/sync/bucket/SqliteBucketStorage.js +0 -162
- package/lib/client/sync/bucket/SqliteBucketStorage.js.map +1 -1
- package/lib/client/sync/stream/AbstractRemote.d.ts +29 -18
- package/lib/client/sync/stream/AbstractRemote.js +155 -188
- package/lib/client/sync/stream/AbstractRemote.js.map +1 -1
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.d.ts +13 -35
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js +150 -448
- package/lib/client/sync/stream/AbstractStreamingSyncImplementation.js.map +1 -1
- package/lib/client/sync/stream/JsonValue.d.ts +7 -0
- package/lib/client/sync/stream/JsonValue.js +2 -0
- package/lib/client/sync/stream/JsonValue.js.map +1 -0
- package/lib/client/sync/stream/core-instruction.d.ts +14 -9
- package/lib/client/sync/stream/core-instruction.js +3 -0
- package/lib/client/sync/stream/core-instruction.js.map +1 -1
- package/lib/db/DBAdapter.d.ts +9 -0
- package/lib/db/DBAdapter.js +8 -1
- package/lib/db/DBAdapter.js.map +1 -1
- package/lib/db/crud/SyncStatus.d.ts +3 -4
- package/lib/db/crud/SyncStatus.js +0 -4
- package/lib/db/crud/SyncStatus.js.map +1 -1
- package/lib/db/schema/RawTable.d.ts +0 -5
- package/lib/db/schema/Schema.d.ts +0 -2
- package/lib/db/schema/Schema.js +0 -2
- package/lib/db/schema/Schema.js.map +1 -1
- package/lib/index.d.ts +2 -6
- package/lib/index.js +1 -6
- package/lib/index.js.map +1 -1
- package/lib/utils/async.d.ts +0 -9
- package/lib/utils/async.js +0 -9
- package/lib/utils/async.js.map +1 -1
- package/lib/utils/stream_transform.d.ts +39 -0
- package/lib/utils/stream_transform.js +206 -0
- package/lib/utils/stream_transform.js.map +1 -0
- package/package.json +15 -10
- package/src/client/AbstractPowerSyncDatabase.ts +3 -3
- package/src/client/ConnectionManager.ts +1 -1
- package/src/client/sync/bucket/BucketStorageAdapter.ts +6 -71
- package/src/client/sync/bucket/SqliteBucketStorage.ts +1 -197
- package/src/client/sync/stream/AbstractRemote.ts +183 -229
- package/src/client/sync/stream/AbstractStreamingSyncImplementation.ts +181 -510
- package/src/client/sync/stream/JsonValue.ts +8 -0
- package/src/client/sync/stream/core-instruction.ts +15 -5
- package/src/db/DBAdapter.ts +20 -2
- package/src/db/crud/SyncStatus.ts +4 -5
- package/src/db/schema/RawTable.ts +0 -5
- package/src/db/schema/Schema.ts +0 -2
- package/src/index.ts +2 -6
- package/src/utils/async.ts +0 -11
- package/src/utils/stream_transform.ts +252 -0
- package/lib/client/sync/bucket/OpType.d.ts +0 -16
- package/lib/client/sync/bucket/OpType.js +0 -23
- package/lib/client/sync/bucket/OpType.js.map +0 -1
- package/lib/client/sync/bucket/OplogEntry.d.ts +0 -23
- package/lib/client/sync/bucket/OplogEntry.js +0 -36
- package/lib/client/sync/bucket/OplogEntry.js.map +0 -1
- package/lib/client/sync/bucket/SyncDataBatch.d.ts +0 -6
- package/lib/client/sync/bucket/SyncDataBatch.js +0 -12
- package/lib/client/sync/bucket/SyncDataBatch.js.map +0 -1
- package/lib/client/sync/bucket/SyncDataBucket.d.ts +0 -40
- package/lib/client/sync/bucket/SyncDataBucket.js +0 -40
- package/lib/client/sync/bucket/SyncDataBucket.js.map +0 -1
- package/lib/client/sync/stream/streaming-sync-types.d.ts +0 -143
- package/lib/client/sync/stream/streaming-sync-types.js +0 -26
- package/lib/client/sync/stream/streaming-sync-types.js.map +0 -1
- package/lib/utils/DataStream.d.ts +0 -62
- package/lib/utils/DataStream.js +0 -169
- package/lib/utils/DataStream.js.map +0 -1
- package/src/client/sync/bucket/OpType.ts +0 -23
- package/src/client/sync/bucket/OplogEntry.ts +0 -50
- package/src/client/sync/bucket/SyncDataBatch.ts +0 -11
- package/src/client/sync/bucket/SyncDataBucket.ts +0 -49
- package/src/client/sync/stream/streaming-sync-types.ts +0 -210
- package/src/utils/DataStream.ts +0 -222
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { BucketChecksum, Checkpoint } from '../bucket/BucketStorageAdapter.js';
|
|
2
|
-
import { CrudEntry, OpId } from '../bucket/CrudEntry.js';
|
|
3
|
-
import { SyncDataBucketJSON } from '../bucket/SyncDataBucket.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* For sync2.json
|
|
7
|
-
*/
|
|
8
|
-
export interface ContinueCheckpointRequest {
|
|
9
|
-
/**
|
|
10
|
-
* Existing bucket states. Only these buckets are synchronized.
|
|
11
|
-
*/
|
|
12
|
-
buckets: BucketRequest[];
|
|
13
|
-
|
|
14
|
-
checkpoint_token: string;
|
|
15
|
-
|
|
16
|
-
limit?: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface SyncNewCheckpointRequest {
|
|
20
|
-
/**
|
|
21
|
-
* Existing bucket states. Used if include_data is specified.
|
|
22
|
-
*/
|
|
23
|
-
buckets?: BucketRequest[];
|
|
24
|
-
|
|
25
|
-
request_checkpoint: {
|
|
26
|
-
/**
|
|
27
|
-
* Whether or not to include an initial data request.
|
|
28
|
-
*/
|
|
29
|
-
include_data: boolean;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Whether or not to compute a checksum.
|
|
33
|
-
*/
|
|
34
|
-
include_checksum: boolean;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
limit?: number;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type SyncRequest = ContinueCheckpointRequest | SyncNewCheckpointRequest;
|
|
41
|
-
|
|
42
|
-
export interface SyncResponse {
|
|
43
|
-
/**
|
|
44
|
-
* Data for the buckets returned. May not have an an entry for each bucket in the request.
|
|
45
|
-
*/
|
|
46
|
-
data?: SyncDataBucketJSON[];
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* True if the response limit has been reached, and another request must be made.
|
|
50
|
-
*/
|
|
51
|
-
has_more: boolean;
|
|
52
|
-
|
|
53
|
-
checkpoint_token?: string;
|
|
54
|
-
|
|
55
|
-
checkpoint?: Checkpoint;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
type JSONValue = string | number | boolean | null | undefined | JSONObject | JSONArray;
|
|
59
|
-
|
|
60
|
-
interface JSONObject {
|
|
61
|
-
[key: string]: JSONValue;
|
|
62
|
-
}
|
|
63
|
-
type JSONArray = JSONValue[];
|
|
64
|
-
|
|
65
|
-
export type StreamingSyncRequestParameterType = JSONValue;
|
|
66
|
-
|
|
67
|
-
export interface StreamingSyncRequest {
|
|
68
|
-
/**
|
|
69
|
-
* Existing bucket states.
|
|
70
|
-
*/
|
|
71
|
-
buckets?: BucketRequest[];
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* If specified, limit the response to only include these buckets.
|
|
75
|
-
*/
|
|
76
|
-
only?: string[];
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Whether or not to compute a checksum for each checkpoint
|
|
80
|
-
*/
|
|
81
|
-
include_checksum: boolean;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Changes the response to stringified data in each OplogEntry
|
|
85
|
-
*/
|
|
86
|
-
raw_data: boolean;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Client parameters to be passed to the sync rules.
|
|
90
|
-
*/
|
|
91
|
-
parameters?: Record<string, StreamingSyncRequestParameterType>;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Application metadata to be included in service logs.
|
|
95
|
-
*/
|
|
96
|
-
app_metadata?: Record<string, string>;
|
|
97
|
-
|
|
98
|
-
client_id?: string;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export interface StreamingSyncCheckpoint {
|
|
102
|
-
checkpoint: Checkpoint;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface StreamingSyncCheckpointDiff {
|
|
106
|
-
checkpoint_diff: {
|
|
107
|
-
last_op_id: OpId;
|
|
108
|
-
updated_buckets: BucketChecksum[];
|
|
109
|
-
removed_buckets: string[];
|
|
110
|
-
write_checkpoint?: string;
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface StreamingSyncDataJSON {
|
|
115
|
-
data: SyncDataBucketJSON;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export interface StreamingSyncCheckpointComplete {
|
|
119
|
-
checkpoint_complete: {
|
|
120
|
-
last_op_id: OpId;
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface StreamingSyncCheckpointPartiallyComplete {
|
|
125
|
-
partial_checkpoint_complete: {
|
|
126
|
-
priority: number;
|
|
127
|
-
last_op_id: OpId;
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export interface StreamingSyncKeepalive {
|
|
132
|
-
/** If specified, token expires in this many seconds. */
|
|
133
|
-
token_expires_in: number;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export type StreamingSyncLine =
|
|
137
|
-
| StreamingSyncDataJSON
|
|
138
|
-
| StreamingSyncCheckpoint
|
|
139
|
-
| StreamingSyncCheckpointDiff
|
|
140
|
-
| StreamingSyncCheckpointComplete
|
|
141
|
-
| StreamingSyncCheckpointPartiallyComplete
|
|
142
|
-
| StreamingSyncKeepalive;
|
|
143
|
-
|
|
144
|
-
export type CrudUploadNotification = { crud_upload_completed: null };
|
|
145
|
-
|
|
146
|
-
export type StreamingSyncLineOrCrudUploadComplete = StreamingSyncLine | CrudUploadNotification;
|
|
147
|
-
|
|
148
|
-
export interface BucketRequest {
|
|
149
|
-
name: string;
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Base-10 number. Sync all data from this bucket with op_id > after.
|
|
153
|
-
*/
|
|
154
|
-
after: OpId;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export function isStreamingSyncData(line: StreamingSyncLine): line is StreamingSyncDataJSON {
|
|
158
|
-
return (line as StreamingSyncDataJSON).data != null;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function isStreamingKeepalive(line: StreamingSyncLine): line is StreamingSyncKeepalive {
|
|
162
|
-
return (line as StreamingSyncKeepalive).token_expires_in != null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function isStreamingSyncCheckpoint(line: StreamingSyncLine): line is StreamingSyncCheckpoint {
|
|
166
|
-
return (line as StreamingSyncCheckpoint).checkpoint != null;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function isStreamingSyncCheckpointComplete(line: StreamingSyncLine): line is StreamingSyncCheckpointComplete {
|
|
170
|
-
return (line as StreamingSyncCheckpointComplete).checkpoint_complete != null;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function isStreamingSyncCheckpointPartiallyComplete(
|
|
174
|
-
line: StreamingSyncLine
|
|
175
|
-
): line is StreamingSyncCheckpointPartiallyComplete {
|
|
176
|
-
return (line as StreamingSyncCheckpointPartiallyComplete).partial_checkpoint_complete != null;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export function isStreamingSyncCheckpointDiff(line: StreamingSyncLine): line is StreamingSyncCheckpointDiff {
|
|
180
|
-
return (line as StreamingSyncCheckpointDiff).checkpoint_diff != null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function isContinueCheckpointRequest(request: SyncRequest): request is ContinueCheckpointRequest {
|
|
184
|
-
return (
|
|
185
|
-
Array.isArray((request as ContinueCheckpointRequest).buckets) &&
|
|
186
|
-
typeof (request as ContinueCheckpointRequest).checkpoint_token == 'string'
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function isSyncNewCheckpointRequest(request: SyncRequest): request is SyncNewCheckpointRequest {
|
|
191
|
-
return typeof (request as SyncNewCheckpointRequest).request_checkpoint == 'object';
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* For crud.json
|
|
196
|
-
*/
|
|
197
|
-
export interface CrudRequest {
|
|
198
|
-
data: CrudEntry[];
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export interface CrudResponse {
|
|
202
|
-
/**
|
|
203
|
-
* A sync response with a checkpoint >= this checkpoint would contain all the changes in this request.
|
|
204
|
-
*
|
|
205
|
-
* Any earlier checkpoint may or may not contain these changes.
|
|
206
|
-
*
|
|
207
|
-
* May be empty when the request contains no ops.
|
|
208
|
-
*/
|
|
209
|
-
checkpoint?: OpId;
|
|
210
|
-
}
|
package/src/utils/DataStream.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import Logger, { ILogger } from 'js-logger';
|
|
2
|
-
import { BaseListener, BaseObserver } from './BaseObserver.js';
|
|
3
|
-
|
|
4
|
-
export type DataStreamOptions<ParsedData, SourceData> = {
|
|
5
|
-
mapLine?: (line: SourceData) => ParsedData;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Close the stream if any consumer throws an error
|
|
9
|
-
*/
|
|
10
|
-
closeOnError?: boolean;
|
|
11
|
-
pressure?: {
|
|
12
|
-
highWaterMark?: number;
|
|
13
|
-
lowWaterMark?: number;
|
|
14
|
-
};
|
|
15
|
-
logger?: ILogger;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type DataStreamCallback<Data extends any = any> = (data: Data) => Promise<void>;
|
|
19
|
-
|
|
20
|
-
export interface DataStreamListener<Data extends any = any> extends BaseListener {
|
|
21
|
-
data: (data: Data) => Promise<void>;
|
|
22
|
-
closed: () => void;
|
|
23
|
-
error: (error: Error) => void;
|
|
24
|
-
highWater: () => Promise<void>;
|
|
25
|
-
lowWater: () => Promise<void>;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const DEFAULT_PRESSURE_LIMITS = {
|
|
29
|
-
highWater: 10,
|
|
30
|
-
lowWater: 0
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* A very basic implementation of a data stream with backpressure support which does not use
|
|
35
|
-
* native JS streams or async iterators.
|
|
36
|
-
* This is handy for environments such as React Native which need polyfills for the above.
|
|
37
|
-
*/
|
|
38
|
-
export class DataStream<ParsedData, SourceData = any> extends BaseObserver<DataStreamListener<ParsedData>> {
|
|
39
|
-
dataQueue: SourceData[];
|
|
40
|
-
|
|
41
|
-
protected isClosed: boolean;
|
|
42
|
-
|
|
43
|
-
protected processingPromise: Promise<void> | null;
|
|
44
|
-
protected notifyDataAdded: (() => void) | null;
|
|
45
|
-
|
|
46
|
-
protected logger: ILogger;
|
|
47
|
-
|
|
48
|
-
protected mapLine: (line: SourceData) => ParsedData;
|
|
49
|
-
|
|
50
|
-
constructor(protected options?: DataStreamOptions<ParsedData, SourceData>) {
|
|
51
|
-
super();
|
|
52
|
-
this.processingPromise = null;
|
|
53
|
-
this.isClosed = false;
|
|
54
|
-
this.dataQueue = [];
|
|
55
|
-
this.mapLine = options?.mapLine ?? ((line) => line as any);
|
|
56
|
-
|
|
57
|
-
this.logger = options?.logger ?? Logger.get('DataStream');
|
|
58
|
-
|
|
59
|
-
if (options?.closeOnError) {
|
|
60
|
-
const l = this.registerListener({
|
|
61
|
-
error: (ex) => {
|
|
62
|
-
l?.();
|
|
63
|
-
this.close();
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get highWatermark() {
|
|
70
|
-
return this.options?.pressure?.highWaterMark ?? DEFAULT_PRESSURE_LIMITS.highWater;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
get lowWatermark() {
|
|
74
|
-
return this.options?.pressure?.lowWaterMark ?? DEFAULT_PRESSURE_LIMITS.lowWater;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
get closed() {
|
|
78
|
-
return this.isClosed;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async close() {
|
|
82
|
-
this.isClosed = true;
|
|
83
|
-
await this.processingPromise;
|
|
84
|
-
this.iterateListeners((l) => l.closed?.());
|
|
85
|
-
// Discard any data in the queue
|
|
86
|
-
this.dataQueue = [];
|
|
87
|
-
this.listeners.clear();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Enqueues data for the consumers to read
|
|
92
|
-
*/
|
|
93
|
-
enqueueData(data: SourceData) {
|
|
94
|
-
if (this.isClosed) {
|
|
95
|
-
throw new Error('Cannot enqueue data into closed stream.');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.dataQueue.push(data);
|
|
99
|
-
this.notifyDataAdded?.();
|
|
100
|
-
|
|
101
|
-
this.processQueue();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Reads data once from the data stream
|
|
106
|
-
* @returns a Data payload or Null if the stream closed.
|
|
107
|
-
*/
|
|
108
|
-
async read(): Promise<ParsedData | null> {
|
|
109
|
-
if (this.closed) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Wait for any pending processing to complete first.
|
|
114
|
-
// This ensures we register our listener before calling processQueue(),
|
|
115
|
-
// avoiding a race where processQueue() sees no reader and returns early.
|
|
116
|
-
if (this.processingPromise) {
|
|
117
|
-
await this.processingPromise;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Re-check after await - stream may have closed while we were waiting
|
|
121
|
-
if (this.closed) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return new Promise((resolve, reject) => {
|
|
126
|
-
const l = this.registerListener({
|
|
127
|
-
data: async (data) => {
|
|
128
|
-
resolve(data);
|
|
129
|
-
// Remove the listener
|
|
130
|
-
l?.();
|
|
131
|
-
},
|
|
132
|
-
closed: () => {
|
|
133
|
-
resolve(null);
|
|
134
|
-
l?.();
|
|
135
|
-
},
|
|
136
|
-
error: (ex) => {
|
|
137
|
-
reject(ex);
|
|
138
|
-
l?.();
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
this.processQueue();
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Executes a callback for each data item in the stream
|
|
148
|
-
*/
|
|
149
|
-
forEach(callback: DataStreamCallback<ParsedData>) {
|
|
150
|
-
if (this.dataQueue.length <= this.lowWatermark) {
|
|
151
|
-
this.iterateAsyncErrored(async (l) => l.lowWater?.());
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return this.registerListener({
|
|
155
|
-
data: callback
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
protected processQueue() {
|
|
160
|
-
if (this.processingPromise) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const promise = (this.processingPromise = this._processQueue());
|
|
165
|
-
promise.finally(() => {
|
|
166
|
-
this.processingPromise = null;
|
|
167
|
-
});
|
|
168
|
-
return promise;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
protected hasDataReader() {
|
|
172
|
-
return Array.from(this.listeners.values()).some((l) => !!l.data);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
protected async _processQueue() {
|
|
176
|
-
/**
|
|
177
|
-
* Allow listeners to mutate the queue before processing.
|
|
178
|
-
* This allows for operations such as dropping or compressing data
|
|
179
|
-
* on high water or requesting more data on low water.
|
|
180
|
-
*/
|
|
181
|
-
if (this.dataQueue.length >= this.highWatermark) {
|
|
182
|
-
await this.iterateAsyncErrored(async (l) => l.highWater?.());
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (this.isClosed || !this.hasDataReader()) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (this.dataQueue.length) {
|
|
190
|
-
const data = this.dataQueue.shift()!;
|
|
191
|
-
const mapped = this.mapLine(data);
|
|
192
|
-
await this.iterateAsyncErrored(async (l) => l.data?.(mapped));
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (this.dataQueue.length <= this.lowWatermark) {
|
|
196
|
-
const dataAdded = new Promise<void>((resolve) => {
|
|
197
|
-
this.notifyDataAdded = resolve;
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
await Promise.race([this.iterateAsyncErrored(async (l) => l.lowWater?.()), dataAdded]);
|
|
201
|
-
this.notifyDataAdded = null;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (this.dataQueue.length > 0) {
|
|
205
|
-
setTimeout(() => this.processQueue());
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
protected async iterateAsyncErrored(cb: (l: Partial<DataStreamListener<ParsedData>>) => Promise<void>) {
|
|
210
|
-
// Important: We need to copy the listeners, as calling a listener could result in adding another
|
|
211
|
-
// listener, resulting in infinite loops.
|
|
212
|
-
const listeners = Array.from(this.listeners.values());
|
|
213
|
-
for (let i of listeners) {
|
|
214
|
-
try {
|
|
215
|
-
await cb(i);
|
|
216
|
-
} catch (ex) {
|
|
217
|
-
this.logger.error(ex);
|
|
218
|
-
this.iterateListeners((l) => l.error?.(ex));
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|