@gholl-studio/pier-connector 0.2.5 → 0.2.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/package.json +1 -1
- package/src/index.js +44 -16
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gholl-studio/pier-connector",
|
|
3
3
|
"author": "gholl",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.7",
|
|
5
5
|
"description": "OpenClaw plugin that connects to the Pier job marketplace. Automatically fetches, executes, and reports distributed tasks for rewards.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "src/index.js",
|
package/src/index.js
CHANGED
|
@@ -477,6 +477,31 @@ export default function register(api) {
|
|
|
477
477
|
// 5. Subscribe to Subjects
|
|
478
478
|
const publicSubject = config.subject;
|
|
479
479
|
const privateSubject = `jobs.node.${config.nodeId}`;
|
|
480
|
+
// 5a. Restore active job subscriptions (BUG-32)
|
|
481
|
+
try {
|
|
482
|
+
const activeConfig = getActiveConfig();
|
|
483
|
+
if (activeConfig.apiBase) {
|
|
484
|
+
logger.info(`[pier-connector] 🔍 Checking for active jobs to restore for node ${config.nodeId}...`);
|
|
485
|
+
const jobsResp = await fetch(`${activeConfig.apiBase}/jobs?assigned_node_id=${config.nodeId}&limit=50`);
|
|
486
|
+
if (jobsResp.ok) {
|
|
487
|
+
const jobsList = await jobsResp.json();
|
|
488
|
+
const activeJobs = (jobsList || []).filter(j => j.status === 'PENDING' || j.status === 'PROCESSING');
|
|
489
|
+
if (activeJobs.length > 0) {
|
|
490
|
+
logger.info(`[pier-connector] ♻️ Restoring ${activeJobs.length} active job subscriptions...`);
|
|
491
|
+
for (const job of activeJobs) {
|
|
492
|
+
if (!jobSubscriptions.has(job.id)) {
|
|
493
|
+
activeNodeJobs.set(job.id, { pierJobId: job.id });
|
|
494
|
+
await subscribeToJobMessages(job.id);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
logger.info('[pier-connector] No active jobs found to restore.');
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
} catch (err) {
|
|
503
|
+
logger.warn(`[pier-connector] ⚠️ Failed to restore active jobs: ${err.message}`);
|
|
504
|
+
}
|
|
480
505
|
|
|
481
506
|
// Public pool with load balancing via JetStream Durable Consumer
|
|
482
507
|
if (publicSubject) {
|
|
@@ -594,14 +619,20 @@ export default function register(api) {
|
|
|
594
619
|
// Use a unique durable name per node and job to avoid replaying acknowledged messages
|
|
595
620
|
const durableName = `pier_chat_${config.nodeId.replace(/[^a-zA-Z0-9]/g, '_')}_${jobId.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
596
621
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
622
|
+
let consumer;
|
|
623
|
+
try {
|
|
624
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
625
|
+
} catch (err) {
|
|
626
|
+
// Only add if it doesn't exist
|
|
627
|
+
await jsm.consumers.add(streamName, {
|
|
628
|
+
durable_name: durableName,
|
|
629
|
+
filter_subject: msgSubject,
|
|
630
|
+
deliver_policy: DeliverPolicy.New, // Reverted to New to stop message storms (BUG-27)
|
|
631
|
+
ack_policy: AckPolicy.Explicit, // Explicit ACK is crucial for deduplication
|
|
632
|
+
ack_wait: 1000 * 60 * 60, // 1 hour ACK wait to allow for long processing (BUG-30)
|
|
633
|
+
});
|
|
634
|
+
consumer = await js.consumers.get(streamName, durableName);
|
|
635
|
+
}
|
|
605
636
|
|
|
606
637
|
const iter = await consumer.consume();
|
|
607
638
|
jobSubscriptions.set(jobId, iter);
|
|
@@ -785,11 +816,10 @@ export default function register(api) {
|
|
|
785
816
|
|
|
786
817
|
// Trigger agent run
|
|
787
818
|
await receiveIncoming(inbound, job.id);
|
|
788
|
-
|
|
789
819
|
} catch (err) {
|
|
790
820
|
jobsFailed++;
|
|
791
821
|
safeRespond(msg, createErrorPayload({
|
|
792
|
-
id: job.id,
|
|
822
|
+
id: (job && job.id) || 'unknown',
|
|
793
823
|
errorCode: 'EXECUTION_FAILED',
|
|
794
824
|
errorMessage: err.message,
|
|
795
825
|
workerId: config.nodeId,
|
|
@@ -808,6 +838,7 @@ export default function register(api) {
|
|
|
808
838
|
logger.info('[pier-connector] NATS connection closed gracefully');
|
|
809
839
|
}
|
|
810
840
|
});
|
|
841
|
+
|
|
811
842
|
} catch (err) {
|
|
812
843
|
connectionStatus = 'error';
|
|
813
844
|
if (heartbeatTimer) clearInterval(heartbeatTimer);
|
|
@@ -820,13 +851,10 @@ export default function register(api) {
|
|
|
820
851
|
logger.info('[pier-connector] 🛑 Stopping background service …');
|
|
821
852
|
connectionStatus = 'stopping';
|
|
822
853
|
|
|
823
|
-
if (
|
|
824
|
-
|
|
825
|
-
|
|
854
|
+
if (nc) {
|
|
855
|
+
await drainConnection(nc, logger);
|
|
856
|
+
nc = null;
|
|
826
857
|
}
|
|
827
|
-
|
|
828
|
-
await drainConnection(nc, logger);
|
|
829
|
-
nc = null;
|
|
830
858
|
connectionStatus = 'disconnected';
|
|
831
859
|
|
|
832
860
|
logger.info('[pier-connector] ✔ Background service stopped');
|