@open-mercato/core 0.7.1-develop.7186.1.6e080a5017 → 0.7.1-develop.7193.1.910a5b0a1e

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.
@@ -334,6 +334,23 @@ export async function GET(req: Request) {
334
334
  )
335
335
  const stalledPartitions = activePartitions.filter((p) => p.status === 'stalled')
336
336
  const scopeCandidate = !preferOrg || !scopeRow || scopeRow.orgMatch ? scopeRow : null
337
+ // A scope-only job (no partition rows, e.g. partitionCount: 1) has nothing in
338
+ // `partitions` for the checks below to see, so its running/stalled/failed state and
339
+ // timestamps must fall back to the scope row itself instead of defaulting to idle/null.
340
+ const computeScopeStatus = (row: any): 'failed' | 'completed' | 'stalled' | 'reindexing' | 'purging' => {
341
+ const heartbeatDate = row.heartbeat_at ? new Date(row.heartbeat_at) : null
342
+ const finishedDate = row.finished_at ? new Date(row.finished_at) : null
343
+ if (finishedDate) return row.status === 'failed' ? 'failed' : 'completed'
344
+ if (!heartbeatDate || Date.now() - heartbeatDate.getTime() > HEARTBEAT_STALE_MS) {
345
+ return 'stalled'
346
+ }
347
+ return (row.status as 'reindexing' | 'purging' | undefined | null) || 'reindexing'
348
+ }
349
+ const scopeStatus = scopeCandidate ? computeScopeStatus(scopeCandidate.row) : null
350
+ const scopeStartedAt = scopeCandidate?.row.started_at ? new Date(scopeCandidate.row.started_at).toISOString() : null
351
+ const scopeFinishedAt = scopeCandidate?.row.finished_at ? new Date(scopeCandidate.row.finished_at).toISOString() : null
352
+ const scopeHeartbeatAt = scopeCandidate?.row.heartbeat_at ? new Date(scopeCandidate.row.heartbeat_at).toISOString() : null
353
+
337
354
  let status: 'idle' | 'reindexing' | 'purging' | 'stalled' | 'failed' = 'idle'
338
355
  if (activePartitions.length) {
339
356
  if (runningPartitions.length) {
@@ -348,13 +365,19 @@ export async function GET(req: Request) {
348
365
  // The run finished but lost records; without this it reports "idle" and the only
349
366
  // hint that anything went wrong is the coverage percentage.
350
367
  status = 'failed'
368
+ } else if (!partitions.length && scopeStatus && scopeStatus !== 'completed') {
369
+ status = scopeStatus
351
370
  }
352
371
 
353
- const startedAt = activePartitions[0]?.startedAt ?? partitions[0]?.startedAt ?? null
372
+ const startedAt = activePartitions[0]?.startedAt
373
+ ?? partitions[0]?.startedAt
374
+ ?? (!partitions.length ? scopeStartedAt : null)
354
375
  const finishedAt = status === 'idle' || status === 'failed'
355
- ? (partitions.find((p) => p.finishedAt)?.finishedAt ?? null)
376
+ ? (partitions.find((p) => p.finishedAt)?.finishedAt ?? (!partitions.length ? scopeFinishedAt : null))
356
377
  : null
357
- const heartbeatAt = activePartitions[0]?.heartbeatAt ?? partitions[0]?.heartbeatAt ?? null
378
+ const heartbeatAt = activePartitions[0]?.heartbeatAt
379
+ ?? partitions[0]?.heartbeatAt
380
+ ?? (!partitions.length ? scopeHeartbeatAt : null)
358
381
  const jobTotalCount = partitions.reduce((sum, p) => sum + (p.totalCount ?? 0), 0)
359
382
  const processedSum = partitions.reduce((sum, p) => sum + (p.processedCount ?? 0), 0)
360
383
  const processedCount = jobTotalCount ? Math.min(jobTotalCount, processedSum) : processedSum || null
@@ -369,18 +392,7 @@ export async function GET(req: Request) {
369
392
  partitions,
370
393
  scope: scopeCandidate
371
394
  ? {
372
- status: (() => {
373
- const heartbeatDate = scopeCandidate!.row.heartbeat_at ? new Date(scopeCandidate!.row.heartbeat_at) : null
374
- const finishedDate = scopeCandidate!.row.finished_at ? new Date(scopeCandidate!.row.finished_at) : null
375
- if (finishedDate) return scopeCandidate!.row.status === 'failed' ? 'failed' : 'completed'
376
- if (
377
- !heartbeatDate ||
378
- Date.now() - heartbeatDate.getTime() > HEARTBEAT_STALE_MS
379
- ) {
380
- return 'stalled'
381
- }
382
- return (scopeCandidate!.row.status as string) || 'reindexing'
383
- })(),
395
+ status: scopeStatus!,
384
396
  processedCount: scopeCandidate.row.processed_count ?? null,
385
397
  totalCount: scopeCandidate.row.total_count ?? null,
386
398
  }