scrapely 1.2.20 → 1.2.21
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/charging.d.ts +21 -0
- package/dist/charging.js +75 -11
- package/package.json +1 -1
package/dist/charging.d.ts
CHANGED
|
@@ -77,6 +77,15 @@ export declare class ChargingManager {
|
|
|
77
77
|
private chargeLimitHit;
|
|
78
78
|
/** Default-dataset rows refused after the limit (one warning, then a count). */
|
|
79
79
|
private refusedDefaultDatasetItems;
|
|
80
|
+
/**
|
|
81
|
+
* Prepaid-row balance: priced events charged through charge() minus rows
|
|
82
|
+
* pushed to the default dataset without a per-row charge. An Actor that
|
|
83
|
+
* charges first and then pushes plainly (charge('product'); pushData(row))
|
|
84
|
+
* has a positive balance after the charge, so the row it already paid for is
|
|
85
|
+
* still saved when that charge used up the spending limit. Push-then-charge
|
|
86
|
+
* Actors never go positive, so they get nothing extra for free.
|
|
87
|
+
*/
|
|
88
|
+
private prepaidRowBalance;
|
|
80
89
|
/** @internal Called by Actor shutdown before the final flush. */
|
|
81
90
|
close(): void;
|
|
82
91
|
/**
|
|
@@ -98,6 +107,18 @@ export declare class ChargingManager {
|
|
|
98
107
|
/** @internal Whether every row of a push with these events is charged a positive price. */
|
|
99
108
|
_isPaidPerItem(eventName: string | undefined, isDefaultDataset: boolean): boolean;
|
|
100
109
|
/** @internal */
|
|
110
|
+
_notePrepaidCharge(eventName: string, chargedCount: number): void;
|
|
111
|
+
/** @internal */
|
|
112
|
+
_isPayPerEvent(): boolean;
|
|
113
|
+
/** @internal Current prepaid-row balance (tests). */
|
|
114
|
+
_prepaidRowBalance(): number;
|
|
115
|
+
/**
|
|
116
|
+
* @internal Account for rows pushed without a per-row charge. Returns how
|
|
117
|
+
* many may be stored: all while the limit is not reached, afterwards only
|
|
118
|
+
* the rows earlier charges already paid for (the positive balance).
|
|
119
|
+
*/
|
|
120
|
+
_takeUnpaidRows(itemCount: number): number;
|
|
121
|
+
/** @internal */
|
|
101
122
|
_refuseDefaultDatasetPush(itemCount: number): boolean;
|
|
102
123
|
/** @internal Whether shutdown has closed this manager to new charges. */
|
|
103
124
|
isClosed(): boolean;
|
package/dist/charging.js
CHANGED
|
@@ -154,6 +154,15 @@ class ChargingManager {
|
|
|
154
154
|
chargeLimitHit = false;
|
|
155
155
|
/** Default-dataset rows refused after the limit (one warning, then a count). */
|
|
156
156
|
refusedDefaultDatasetItems = 0;
|
|
157
|
+
/**
|
|
158
|
+
* Prepaid-row balance: priced events charged through charge() minus rows
|
|
159
|
+
* pushed to the default dataset without a per-row charge. An Actor that
|
|
160
|
+
* charges first and then pushes plainly (charge('product'); pushData(row))
|
|
161
|
+
* has a positive balance after the charge, so the row it already paid for is
|
|
162
|
+
* still saved when that charge used up the spending limit. Push-then-charge
|
|
163
|
+
* Actors never go positive, so they get nothing extra for free.
|
|
164
|
+
*/
|
|
165
|
+
prepaidRowBalance = 0;
|
|
157
166
|
/** @internal Called by Actor shutdown before the final flush. */
|
|
158
167
|
close() {
|
|
159
168
|
this._closed = true;
|
|
@@ -216,9 +225,49 @@ class ChargingManager {
|
|
|
216
225
|
return names.some((name) => (this.calculateEventPrice(name) ?? 0) > 0);
|
|
217
226
|
}
|
|
218
227
|
/** @internal */
|
|
228
|
+
_notePrepaidCharge(eventName, chargedCount) {
|
|
229
|
+
if (chargedCount > 0 && !isSyntheticEvent(eventName) && (this.pricingInfo[eventName]?.price ?? 0) > 0) {
|
|
230
|
+
this.prepaidRowBalance += chargedCount;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/** @internal */
|
|
234
|
+
_isPayPerEvent() {
|
|
235
|
+
return this.chargingState !== undefined && this.isPayPerEvent;
|
|
236
|
+
}
|
|
237
|
+
/** @internal Current prepaid-row balance (tests). */
|
|
238
|
+
_prepaidRowBalance() {
|
|
239
|
+
return this.prepaidRowBalance;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* @internal Account for rows pushed without a per-row charge. Returns how
|
|
243
|
+
* many may be stored: all while the limit is not reached, afterwards only
|
|
244
|
+
* the rows earlier charges already paid for (the positive balance).
|
|
245
|
+
*/
|
|
246
|
+
_takeUnpaidRows(itemCount) {
|
|
247
|
+
if (itemCount <= 0)
|
|
248
|
+
return 0;
|
|
249
|
+
if (!this.isChargeLimitReached()) {
|
|
250
|
+
this.prepaidRowBalance -= itemCount;
|
|
251
|
+
return itemCount;
|
|
252
|
+
}
|
|
253
|
+
const allowed = Math.max(0, Math.min(itemCount, this.prepaidRowBalance));
|
|
254
|
+
this.prepaidRowBalance -= allowed;
|
|
255
|
+
return allowed;
|
|
256
|
+
}
|
|
257
|
+
/** @internal */
|
|
219
258
|
_refuseDefaultDatasetPush(itemCount) {
|
|
220
|
-
if (itemCount <= 0 || !this.
|
|
259
|
+
if (itemCount <= 0 || !this.isPayPerEvent)
|
|
260
|
+
return false;
|
|
261
|
+
if (!this.isChargeLimitReached()) {
|
|
262
|
+
this._takeUnpaidRows(itemCount);
|
|
221
263
|
return false;
|
|
264
|
+
}
|
|
265
|
+
// All-or-nothing here (storage clients cannot store a slice): store the
|
|
266
|
+
// batch only when earlier charges paid for every row of it.
|
|
267
|
+
if (this.prepaidRowBalance >= itemCount) {
|
|
268
|
+
this.prepaidRowBalance -= itemCount;
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
222
271
|
this._noteRefusedDefaultDatasetItems(itemCount);
|
|
223
272
|
return true;
|
|
224
273
|
}
|
|
@@ -771,7 +820,11 @@ class ChargingManager {
|
|
|
771
820
|
}
|
|
772
821
|
}
|
|
773
822
|
async charge({ eventName, count = 1 }) {
|
|
774
|
-
return this._withOperationLock(() =>
|
|
823
|
+
return this._withOperationLock(async () => {
|
|
824
|
+
const result = await this._chargeExclusive({ eventName, count });
|
|
825
|
+
this._notePrepaidCharge(eventName, result.chargedCount);
|
|
826
|
+
return result;
|
|
827
|
+
});
|
|
775
828
|
}
|
|
776
829
|
/** @internal Caller must hold the operation lock. */
|
|
777
830
|
async _chargeExclusive({ eventName, count = 1 }) {
|
|
@@ -983,16 +1036,27 @@ async function pushDataAndCharge({ chargingManager, items, eventName, isDefaultD
|
|
|
983
1036
|
// default-dataset push that does not pay per row (no event, or only free
|
|
984
1037
|
// events) stores nothing. Paid pushes go on below, where the budget cap
|
|
985
1038
|
// stores only the rows that are actually charged.
|
|
1039
|
+
// Rows the Actor already paid for with an earlier charge() (charge first,
|
|
1040
|
+
// then a plain push) are still stored: see ChargingManager._takeUnpaidRows.
|
|
1041
|
+
// The result still reports the limit, so the Actor stops after them.
|
|
1042
|
+
let unpaidPastLimit = false;
|
|
986
1043
|
if (isDefaultDataset &&
|
|
987
1044
|
requested > 0 &&
|
|
988
|
-
chargingManager.
|
|
1045
|
+
chargingManager._isPayPerEvent() &&
|
|
989
1046
|
!chargingManager._isPaidPerItem(eventName, isDefaultDataset)) {
|
|
990
|
-
chargingManager.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1047
|
+
unpaidPastLimit = chargingManager.isChargeLimitReached?.() ?? false;
|
|
1048
|
+
const allowed = chargingManager._takeUnpaidRows(requested);
|
|
1049
|
+
if (allowed < requested) {
|
|
1050
|
+
chargingManager._noteRefusedDefaultDatasetItems(requested - allowed);
|
|
1051
|
+
if (allowed === 0) {
|
|
1052
|
+
return {
|
|
1053
|
+
eventChargeLimitReached: true,
|
|
1054
|
+
chargedCount: 0,
|
|
1055
|
+
chargeableWithinLimit: chargingManager._chargeableWithinLimit?.() ?? {},
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
items = (Array.isArray(items) ? items.slice(0, allowed) : items);
|
|
1059
|
+
}
|
|
996
1060
|
}
|
|
997
1061
|
const { limitedItems, eventsToCharge } = chargingManager.calculatePushDataLimits({
|
|
998
1062
|
items,
|
|
@@ -1161,12 +1225,12 @@ async function pushDataAndCharge({ chargingManager, items, eventName, isDefaultD
|
|
|
1161
1225
|
}
|
|
1162
1226
|
throw pushErr;
|
|
1163
1227
|
}
|
|
1164
|
-
return chargeResult;
|
|
1228
|
+
return unpaidPastLimit ? { ...chargeResult, eventChargeLimitReached: true } : chargeResult;
|
|
1165
1229
|
}
|
|
1166
1230
|
// No billable events — still persist the budget-limited items.
|
|
1167
1231
|
await chargeGatedPush.run(true, () => pushFn(Array.isArray(items) ? limitedItems : limitedItems[0]));
|
|
1168
1232
|
return {
|
|
1169
|
-
eventChargeLimitReached:
|
|
1233
|
+
eventChargeLimitReached: unpaidPastLimit,
|
|
1170
1234
|
chargedCount: 0,
|
|
1171
1235
|
chargeableWithinLimit: {},
|
|
1172
1236
|
};
|