channel-worker 2.5.5 → 2.5.7
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/lib/command-poller.js +24 -0
- package/package.json +1 -1
- package/scripts/upload_facebook.js +13 -0
package/lib/command-poller.js
CHANGED
|
@@ -139,6 +139,26 @@ class CommandPoller {
|
|
|
139
139
|
}
|
|
140
140
|
// Strip the '_pw' suffix to derive the script name (upload_youtube_pw → upload_youtube).
|
|
141
141
|
const scriptName = command.type.replace(/_pw$/, '');
|
|
142
|
+
|
|
143
|
+
// PER-PROFILE MUTEX — two _pw scripts can't share the same NST profile.
|
|
144
|
+
// The NST browser is launched once and shared via CDP; concurrent
|
|
145
|
+
// page.goto / navigation calls from sibling scripts abort each other
|
|
146
|
+
// (saw `net::ERR_ABORTED` on FB while YT was navigating during the same
|
|
147
|
+
// publish click). Different profiles still run in parallel — this lock
|
|
148
|
+
// only serializes within a profile. Wait up to 30 min with 5s polling
|
|
149
|
+
// (upload typically 1-3 min); stale-cleanup picks up zombies separately.
|
|
150
|
+
if (!this._pwInFlight) this._pwInFlight = new Map();
|
|
151
|
+
const MUTEX_MAX_WAIT_MS = 30 * 60 * 1000;
|
|
152
|
+
const waitStart = Date.now();
|
|
153
|
+
while (this._pwInFlight.has(profileId)) {
|
|
154
|
+
if (Date.now() - waitStart > MUTEX_MAX_WAIT_MS) {
|
|
155
|
+
await this.api.updateCommand(command._id, { status: 'failed', error: `pw mutex timeout — profile ${profileId} busy with ${this._pwInFlight.get(profileId)} for >30min` });
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
console.log(`[commands/pw] ${command.type} waiting — profile ${profileId} busy with ${this._pwInFlight.get(profileId)}`);
|
|
159
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
160
|
+
}
|
|
161
|
+
this._pwInFlight.set(profileId, command.type);
|
|
142
162
|
console.log(`[commands/pw] ${command.type} → scripts/${scriptName}.js (profile=${profileId})`);
|
|
143
163
|
|
|
144
164
|
// Lazy-init NST manager (same pattern as the other handlers).
|
|
@@ -177,6 +197,10 @@ class CommandPoller {
|
|
|
177
197
|
} catch (err) {
|
|
178
198
|
console.error(`[commands/pw] ${command.type} failed: ${err.message}`);
|
|
179
199
|
await this.api.postCommandResult(command._id, { status: 'failed', error: String(err.message || err).slice(0, 500) });
|
|
200
|
+
} finally {
|
|
201
|
+
// Always release the per-profile mutex — even on throw — or sibling
|
|
202
|
+
// pw cmds for the same profile would hang forever.
|
|
203
|
+
if (this._pwInFlight) this._pwInFlight.delete(profileId);
|
|
180
204
|
}
|
|
181
205
|
}
|
|
182
206
|
|
package/package.json
CHANGED
|
@@ -1257,6 +1257,19 @@ async function run({ page, payload, log }) {
|
|
|
1257
1257
|
// of publishing).
|
|
1258
1258
|
const pub = await findByVerbs(publishVerbs, { requireBottomHalf: true });
|
|
1259
1259
|
if (pub) {
|
|
1260
|
+
// Strict-input contract: if the caller supplied a thumbnail_url but
|
|
1261
|
+
// we never opened the "Chỉnh sửa hình thu nhỏ" overlay (FB didn't
|
|
1262
|
+
// render it / DOM selector miss), refuse to publish — the reel
|
|
1263
|
+
// would otherwise ship with FB's auto-generated thumb and the user
|
|
1264
|
+
// sees no custom artwork. Surface as a hard failure so the daemon
|
|
1265
|
+
// retries with a fresh page load instead of silently shipping bad
|
|
1266
|
+
// output. (Observed on reel 1506614811005729: step 1 → click Tiếp
|
|
1267
|
+
// → publish, the thumb-edit pill never appeared.)
|
|
1268
|
+
if (thumbPath && !customThumbDone) {
|
|
1269
|
+
await dumpInventory(page, log, `thumb-step-missed-${step + 1}`);
|
|
1270
|
+
await dumpFailure(page, `thumb-step-missed-${step + 1}`, log);
|
|
1271
|
+
throw new Error(`FB publish: thumbnail_url provided but the "Chỉnh sửa hình thu nhỏ" overlay was never detected before publish (step ${step + 1}). Refusing to ship without custom thumb. Inspect dump screenshots in Temp\\cm-worker-pw\\.`);
|
|
1272
|
+
}
|
|
1260
1273
|
log('info', `[fb-pw] click publish "${pub.verb}" via "${pub.sel}" (step ${step + 1})`);
|
|
1261
1274
|
// Snapshot the captured-IDs list RIGHT BEFORE the publish click. The
|
|
1262
1275
|
// network listener captures from EVERY graph response, including the
|