jettypod 4.4.49 → 4.4.50

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/lib/merge-lock.js +19 -10
  2. package/package.json +1 -1
package/lib/merge-lock.js CHANGED
@@ -36,21 +36,30 @@ async function acquireMergeLock(db, workItemId, instanceId = null, options = {})
36
36
 
37
37
  const maxWait = options.maxWait || 60000; // 1 minute default
38
38
  const pollInterval = options.pollInterval || 1500; // 1.5 seconds
39
- const staleThreshold = options.staleThreshold || 120000; // 2 minutes (reduced from 5 minutes)
39
+ const staleThreshold = options.staleThreshold || 90000; // 90 seconds - locks auto-expire
40
40
  const startTime = Date.now();
41
41
 
42
42
  // Generate instance identifier
43
43
  const lockedBy = instanceId || `${os.hostname()}-${process.pid}`;
44
44
 
45
- // Proactive cleanup of stale locks before attempting acquisition
46
- try {
47
- await cleanupStaleLocks(db, staleThreshold);
48
- } catch (cleanupErr) {
49
- // Log but don't fail - cleanup is best-effort
50
- console.warn(`Warning: Failed to cleanup stale locks: ${cleanupErr.message}`);
51
- }
45
+ let pollCount = 0;
52
46
 
53
47
  while (Date.now() - startTime < maxWait) {
48
+ // Cleanup stale locks every 5 polls (every ~10 seconds with 2s poll interval)
49
+ // This ensures orphaned locks get cleaned up during the wait
50
+ if (pollCount % 5 === 0) {
51
+ try {
52
+ const cleaned = await cleanupStaleLocks(db, staleThreshold);
53
+ if (cleaned > 0) {
54
+ console.log(`🧹 Cleaned ${cleaned} stale merge lock(s)`);
55
+ }
56
+ } catch (cleanupErr) {
57
+ // Log but don't fail - cleanup is best-effort
58
+ console.warn(`Warning: Failed to cleanup stale locks: ${cleanupErr.message}`);
59
+ }
60
+ }
61
+ pollCount++;
62
+
54
63
  // Check if lock exists
55
64
  const existingLock = await checkExistingLock(db);
56
65
 
@@ -118,7 +127,7 @@ function insertLock(db, workItemId, lockedBy) {
118
127
  * @param {number|Object} staleThresholdOrOptions - Age threshold in milliseconds (default: 120000), or options object with staleThreshold
119
128
  * @returns {Promise<number>} Count of locks removed
120
129
  */
121
- function cleanupStaleLocks(db, staleThresholdOrOptions = 120000) {
130
+ function cleanupStaleLocks(db, staleThresholdOrOptions = 90000) {
122
131
  if (!db) {
123
132
  return Promise.reject(new Error('Database connection required'));
124
133
  }
@@ -126,7 +135,7 @@ function cleanupStaleLocks(db, staleThresholdOrOptions = 120000) {
126
135
  // Support both number (old API) and options object (new API)
127
136
  let staleThresholdMs;
128
137
  if (typeof staleThresholdOrOptions === 'object') {
129
- staleThresholdMs = staleThresholdOrOptions.staleThreshold || 120000;
138
+ staleThresholdMs = staleThresholdOrOptions.staleThreshold || 90000;
130
139
  } else {
131
140
  staleThresholdMs = staleThresholdOrOptions;
132
141
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "4.4.49",
3
+ "version": "4.4.50",
4
4
  "description": "AI-powered development workflow manager with TDD, BDD, and automatic test generation",
5
5
  "main": "jettypod.js",
6
6
  "bin": {