@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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. 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.5",
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
- const cInfo = await jsm.consumers.add(streamName, {
598
- durable_name: durableName,
599
- filter_subject: msgSubject,
600
- deliver_policy: DeliverPolicy.New, // Reverted to New to stop message storms (BUG-27)
601
- ack_policy: AckPolicy.Explicit, // Explicit ACK is crucial for deduplication
602
- ack_wait: 1000 * 60 * 60, // 1 hour ACK wait to allow for long processing (BUG-30)
603
- });
604
- const consumer = await js.consumers.get(streamName, cInfo.name);
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 (subscription) {
824
- subscription.unsubscribe();
825
- subscription = null;
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');