@open-mercato/core 0.6.7-develop.6653.1.b5bc7194a0 → 0.6.7-develop.6661.1.0043ed1d03
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/.turbo/turbo-build.log +1 -1
- package/dist/modules/business_rules/lib/value-resolver.js +7 -0
- package/dist/modules/business_rules/lib/value-resolver.js.map +2 -2
- package/dist/modules/communication_channels/lib/pg-errors.js +1 -7
- package/dist/modules/communication_channels/lib/pg-errors.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +22 -8
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/currencies/commands/exchange-rates.js +22 -8
- package/dist/modules/currencies/commands/exchange-rates.js.map +2 -2
- package/dist/modules/currencies/commands/scope.js +22 -0
- package/dist/modules/currencies/commands/scope.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivitiesSection.js +5 -4
- package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/ActivityHistorySection.js +5 -4
- package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +2 -2
- package/dist/modules/feature_toggles/api/global/route.js +6 -0
- package/dist/modules/feature_toggles/api/global/route.js.map +2 -2
- package/dist/modules/feature_toggles/commands/global.js +9 -9
- package/dist/modules/feature_toggles/commands/global.js.map +2 -2
- package/dist/modules/query_index/api/openapi.js +2 -2
- package/dist/modules/query_index/api/openapi.js.map +2 -2
- package/dist/modules/query_index/api/status.js +6 -4
- package/dist/modules/query_index/api/status.js.map +2 -2
- package/dist/modules/query_index/cli.js +31 -28
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +4 -1
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/query_index/lib/batch.js +163 -44
- package/dist/modules/query_index/lib/batch.js.map +3 -3
- package/dist/modules/query_index/lib/jobs.js +3 -2
- package/dist/modules/query_index/lib/jobs.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +50 -16
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/query_index/lib/stale.js +3 -0
- package/dist/modules/query_index/lib/stale.js.map +2 -2
- package/dist/modules/query_index/lib/subscriber-scope.js +63 -10
- package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
- package/dist/modules/query_index/subscribers/delete_one.js +20 -6
- package/dist/modules/query_index/subscribers/delete_one.js.map +2 -2
- package/dist/modules/query_index/subscribers/upsert_one.js +8 -3
- package/dist/modules/query_index/subscribers/upsert_one.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js +2 -0
- package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -0
- package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/business_rules/lib/value-resolver.ts +16 -0
- package/src/modules/communication_channels/lib/pg-errors.ts +3 -10
- package/src/modules/currencies/commands/currencies.ts +26 -8
- package/src/modules/currencies/commands/exchange-rates.ts +26 -8
- package/src/modules/currencies/commands/scope.ts +32 -0
- package/src/modules/customers/components/detail/ActivitiesSection.tsx +10 -6
- package/src/modules/customers/components/detail/ActivityHistorySection.tsx +6 -3
- package/src/modules/feature_toggles/api/global/route.ts +7 -1
- package/src/modules/feature_toggles/commands/global.ts +9 -12
- package/src/modules/query_index/api/openapi.ts +2 -2
- package/src/modules/query_index/api/status.ts +14 -5
- package/src/modules/query_index/cli.ts +36 -28
- package/src/modules/query_index/components/QueryIndexesTable.tsx +7 -4
- package/src/modules/query_index/i18n/de.json +2 -0
- package/src/modules/query_index/i18n/en.json +2 -0
- package/src/modules/query_index/i18n/es.json +2 -0
- package/src/modules/query_index/i18n/pl.json +2 -0
- package/src/modules/query_index/lib/batch.ts +244 -67
- package/src/modules/query_index/lib/jobs.ts +11 -0
- package/src/modules/query_index/lib/reindexer.ts +69 -16
- package/src/modules/query_index/lib/stale.ts +10 -0
- package/src/modules/query_index/lib/subscriber-scope.ts +98 -14
- package/src/modules/query_index/subscribers/delete_one.ts +21 -10
- package/src/modules/query_index/subscribers/upsert_one.ts +8 -3
- package/src/modules/workflows/AGENTS.md +22 -0
- package/src/modules/workflows/api/definitions/[id]/customize/route.ts +9 -0
- package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +7 -0
|
@@ -52,14 +52,11 @@ const featureToggleCrudIndexer = { entityType: E.feature_toggles.feature_toggle
|
|
|
52
52
|
|
|
53
53
|
const FEATURE_TOGGLE_LOCK_RESOURCE_KIND = 'feature_toggles.feature_toggle'
|
|
54
54
|
|
|
55
|
-
function featureToggleIdentifiers(
|
|
56
|
-
toggle: FeatureToggle | ToggleSnapshot,
|
|
57
|
-
ctx: { auth?: { tenantId?: string | null } | null },
|
|
58
|
-
) {
|
|
55
|
+
function featureToggleIdentifiers(toggle: FeatureToggle | ToggleSnapshot) {
|
|
59
56
|
return {
|
|
60
57
|
id: toggle.id,
|
|
61
58
|
organizationId: null,
|
|
62
|
-
tenantId:
|
|
59
|
+
tenantId: null,
|
|
63
60
|
}
|
|
64
61
|
}
|
|
65
62
|
|
|
@@ -113,7 +110,7 @@ const createToggleCommand: CommandHandler<ToggleCreateInput, { toggleId: string
|
|
|
113
110
|
dataEngine,
|
|
114
111
|
action: 'created',
|
|
115
112
|
entity: toggle,
|
|
116
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
113
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
117
114
|
syncOrigin: ctx.syncOrigin,
|
|
118
115
|
indexer: featureToggleCrudIndexer,
|
|
119
116
|
})
|
|
@@ -157,7 +154,7 @@ const createToggleCommand: CommandHandler<ToggleCreateInput, { toggleId: string
|
|
|
157
154
|
dataEngine,
|
|
158
155
|
action: 'deleted',
|
|
159
156
|
entity: toggle,
|
|
160
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
157
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
161
158
|
syncOrigin: ctx.syncOrigin,
|
|
162
159
|
indexer: featureToggleCrudIndexer,
|
|
163
160
|
})
|
|
@@ -196,7 +193,7 @@ const createToggleCommand: CommandHandler<ToggleCreateInput, { toggleId: string
|
|
|
196
193
|
dataEngine,
|
|
197
194
|
action: 'created',
|
|
198
195
|
entity: toggle,
|
|
199
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
196
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
200
197
|
syncOrigin: ctx.syncOrigin,
|
|
201
198
|
indexer: featureToggleCrudIndexer,
|
|
202
199
|
})
|
|
@@ -245,7 +242,7 @@ const updateToggleCommand: CommandHandler<ToggleUpdateInput, { toggleId: string
|
|
|
245
242
|
dataEngine,
|
|
246
243
|
action: 'updated',
|
|
247
244
|
entity: toggle,
|
|
248
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
245
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
249
246
|
syncOrigin: ctx.syncOrigin,
|
|
250
247
|
indexer: featureToggleCrudIndexer,
|
|
251
248
|
})
|
|
@@ -328,7 +325,7 @@ const updateToggleCommand: CommandHandler<ToggleUpdateInput, { toggleId: string
|
|
|
328
325
|
dataEngine,
|
|
329
326
|
action: 'updated',
|
|
330
327
|
entity: toggle,
|
|
331
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
328
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
332
329
|
syncOrigin: ctx.syncOrigin,
|
|
333
330
|
indexer: featureToggleCrudIndexer,
|
|
334
331
|
})
|
|
@@ -369,7 +366,7 @@ const deleteToggleCommand: CommandHandler<{ body?: Record<string, unknown>; quer
|
|
|
369
366
|
dataEngine,
|
|
370
367
|
action: 'deleted',
|
|
371
368
|
entity: toggle,
|
|
372
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
369
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
373
370
|
syncOrigin: ctx.syncOrigin,
|
|
374
371
|
indexer: featureToggleCrudIndexer,
|
|
375
372
|
})
|
|
@@ -443,7 +440,7 @@ const deleteToggleCommand: CommandHandler<{ body?: Record<string, unknown>; quer
|
|
|
443
440
|
dataEngine,
|
|
444
441
|
action: 'updated',
|
|
445
442
|
entity: toggle,
|
|
446
|
-
identifiers: featureToggleIdentifiers(toggle
|
|
443
|
+
identifiers: featureToggleIdentifiers(toggle),
|
|
447
444
|
syncOrigin: ctx.syncOrigin,
|
|
448
445
|
indexer: featureToggleCrudIndexer,
|
|
449
446
|
})
|
|
@@ -10,7 +10,7 @@ export const queryIndexErrorSchema = z.object({
|
|
|
10
10
|
export const queryIndexPartitionSchema = z.object({
|
|
11
11
|
partitionIndex: z.number().int().nonnegative().nullable().optional(),
|
|
12
12
|
partitionCount: z.number().int().positive().nullable().optional(),
|
|
13
|
-
status: z.enum(['reindexing', 'purging', 'stalled', 'completed']),
|
|
13
|
+
status: z.enum(['reindexing', 'purging', 'stalled', 'completed', 'failed']),
|
|
14
14
|
startedAt: z.string().nullable().optional(),
|
|
15
15
|
finishedAt: z.string().nullable().optional(),
|
|
16
16
|
heartbeatAt: z.string().nullable().optional(),
|
|
@@ -19,7 +19,7 @@ export const queryIndexPartitionSchema = z.object({
|
|
|
19
19
|
})
|
|
20
20
|
|
|
21
21
|
export const queryIndexJobSchema = z.object({
|
|
22
|
-
status: z.enum(['idle', 'reindexing', 'purging', 'stalled']),
|
|
22
|
+
status: z.enum(['idle', 'reindexing', 'purging', 'stalled', 'failed']),
|
|
23
23
|
startedAt: z.string().nullable().optional(),
|
|
24
24
|
finishedAt: z.string().nullable().optional(),
|
|
25
25
|
heartbeatAt: z.string().nullable().optional(),
|
|
@@ -240,7 +240,7 @@ export async function GET(req: Request) {
|
|
|
240
240
|
const stalled =
|
|
241
241
|
!finishedDate && (!heartbeatDate || Date.now() - heartbeatDate.getTime() > HEARTBEAT_STALE_MS)
|
|
242
242
|
const state = finishedDate
|
|
243
|
-
? 'completed'
|
|
243
|
+
? (row.status === 'failed' ? 'failed' : 'completed')
|
|
244
244
|
: stalled
|
|
245
245
|
? 'stalled'
|
|
246
246
|
: (row.status as string) || 'reindexing'
|
|
@@ -261,22 +261,31 @@ export async function GET(req: Request) {
|
|
|
261
261
|
(p) => p.status === 'reindexing' || p.status === 'purging',
|
|
262
262
|
)
|
|
263
263
|
const stalledPartitions = activePartitions.filter((p) => p.status === 'stalled')
|
|
264
|
-
|
|
264
|
+
const scopeCandidate = !preferOrg || !scopeRow || scopeRow.orgMatch ? scopeRow : null
|
|
265
|
+
let status: 'idle' | 'reindexing' | 'purging' | 'stalled' | 'failed' = 'idle'
|
|
265
266
|
if (activePartitions.length) {
|
|
266
267
|
if (runningPartitions.length) {
|
|
267
268
|
status = runningPartitions.some((p) => p.status === 'purging') ? 'purging' : 'reindexing'
|
|
268
269
|
} else if (stalledPartitions.length) {
|
|
269
270
|
status = 'stalled'
|
|
270
271
|
}
|
|
272
|
+
} else if (
|
|
273
|
+
partitions.some((p) => p.status === 'failed')
|
|
274
|
+
|| (scopeCandidate?.row.finished_at && scopeCandidate.row.status === 'failed')
|
|
275
|
+
) {
|
|
276
|
+
// The run finished but lost records; without this it reports "idle" and the only
|
|
277
|
+
// hint that anything went wrong is the coverage percentage.
|
|
278
|
+
status = 'failed'
|
|
271
279
|
}
|
|
272
280
|
|
|
273
281
|
const startedAt = activePartitions[0]?.startedAt ?? partitions[0]?.startedAt ?? null
|
|
274
|
-
const finishedAt = status === 'idle'
|
|
282
|
+
const finishedAt = status === 'idle' || status === 'failed'
|
|
283
|
+
? (partitions.find((p) => p.finishedAt)?.finishedAt ?? null)
|
|
284
|
+
: null
|
|
275
285
|
const heartbeatAt = activePartitions[0]?.heartbeatAt ?? partitions[0]?.heartbeatAt ?? null
|
|
276
286
|
const jobTotalCount = partitions.reduce((sum, p) => sum + (p.totalCount ?? 0), 0)
|
|
277
287
|
const processedSum = partitions.reduce((sum, p) => sum + (p.processedCount ?? 0), 0)
|
|
278
288
|
const processedCount = jobTotalCount ? Math.min(jobTotalCount, processedSum) : processedSum || null
|
|
279
|
-
const scopeCandidate = !preferOrg || !scopeRow || scopeRow.orgMatch ? scopeRow : null
|
|
280
289
|
|
|
281
290
|
return {
|
|
282
291
|
status,
|
|
@@ -291,7 +300,7 @@ export async function GET(req: Request) {
|
|
|
291
300
|
status: (() => {
|
|
292
301
|
const heartbeatDate = scopeCandidate!.row.heartbeat_at ? new Date(scopeCandidate!.row.heartbeat_at) : null
|
|
293
302
|
const finishedDate = scopeCandidate!.row.finished_at ? new Date(scopeCandidate!.row.finished_at) : null
|
|
294
|
-
if (finishedDate) return 'completed'
|
|
303
|
+
if (finishedDate) return scopeCandidate!.row.status === 'failed' ? 'failed' : 'completed'
|
|
295
304
|
if (
|
|
296
305
|
!heartbeatDate ||
|
|
297
306
|
Date.now() - heartbeatDate.getTime() > HEARTBEAT_STALE_MS
|
|
@@ -14,7 +14,13 @@ type ProgressBarHandle = {
|
|
|
14
14
|
import { resolveEntityTableName } from '@open-mercato/shared/lib/query/engine'
|
|
15
15
|
import { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'
|
|
16
16
|
import { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
upsertIndexBatch,
|
|
19
|
+
assertIndexBatchWritesLanded,
|
|
20
|
+
createEmptyUpsertIndexBatchResult,
|
|
21
|
+
mergeUpsertIndexBatchResults,
|
|
22
|
+
type AnyRow,
|
|
23
|
+
} from './lib/batch'
|
|
18
24
|
import { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'
|
|
19
25
|
import { purgeIndexScope } from './lib/purge'
|
|
20
26
|
import { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'
|
|
@@ -185,21 +191,20 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
185
191
|
const encryption = resolveTenantEncryptionService(em as any)
|
|
186
192
|
const dekKeyCache = new Map<string | null, string | null>()
|
|
187
193
|
|
|
194
|
+
// Neither helper swallows failures: upsertIndexBatch treats a failed encrypt as a
|
|
195
|
+
// failed row (writing the plaintext document instead would break encryption at rest)
|
|
196
|
+
// and records a failed decrypt against fulltext.
|
|
188
197
|
const encryptDoc = async (
|
|
189
198
|
targetEntity: string,
|
|
190
199
|
doc: Record<string, unknown>,
|
|
191
200
|
scope: { organizationId: string | null; tenantId: string | null },
|
|
192
201
|
) => {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
)
|
|
200
|
-
} catch {
|
|
201
|
-
return doc
|
|
202
|
-
}
|
|
202
|
+
return await encryptIndexDocForStorage(
|
|
203
|
+
targetEntity,
|
|
204
|
+
doc,
|
|
205
|
+
{ tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },
|
|
206
|
+
encryption,
|
|
207
|
+
)
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
const decryptDoc = async (
|
|
@@ -207,17 +212,13 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
207
212
|
doc: Record<string, unknown>,
|
|
208
213
|
scope: { organizationId: string | null; tenantId: string | null },
|
|
209
214
|
) => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
)
|
|
218
|
-
} catch {
|
|
219
|
-
return doc
|
|
220
|
-
}
|
|
215
|
+
return await decryptIndexDocForSearch(
|
|
216
|
+
targetEntity,
|
|
217
|
+
doc,
|
|
218
|
+
{ tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },
|
|
219
|
+
encryption,
|
|
220
|
+
dekKeyCache,
|
|
221
|
+
)
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
const applyFilters = <QB extends { where: (...args: any[]) => QB }>(q: QB): QB => {
|
|
@@ -244,10 +245,11 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
244
245
|
.executeTakeFirst() as AnyRow | undefined
|
|
245
246
|
if (!row) return { processed: 0, matched: 0 }
|
|
246
247
|
const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)
|
|
247
|
-
await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })
|
|
248
|
-
bar.update(
|
|
248
|
+
const singleResult = await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })
|
|
249
|
+
bar.update(singleResult.written)
|
|
249
250
|
bar.complete()
|
|
250
|
-
|
|
251
|
+
assertIndexBatchWritesLanded(entityType, singleResult)
|
|
252
|
+
return { processed: singleResult.written, matched: 1 }
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
const countRow = await applyFilters(
|
|
@@ -265,10 +267,12 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
265
267
|
|
|
266
268
|
const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)
|
|
267
269
|
let processed = 0
|
|
270
|
+
let fetched = 0
|
|
268
271
|
let cursorOffset = effectiveOffset
|
|
269
272
|
let remaining = limitValue
|
|
273
|
+
const writeTotals = createEmptyUpsertIndexBatchResult()
|
|
270
274
|
|
|
271
|
-
while (
|
|
275
|
+
while (fetched < intended) {
|
|
272
276
|
const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize
|
|
273
277
|
const chunk = await applyFilters(
|
|
274
278
|
db
|
|
@@ -280,12 +284,14 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
280
284
|
).execute() as AnyRow[]
|
|
281
285
|
if (!chunk.length) break
|
|
282
286
|
|
|
283
|
-
await upsertIndexBatch(db, entityType, chunk as AnyRow[], {
|
|
287
|
+
const chunkResult = await upsertIndexBatch(db, entityType, chunk as AnyRow[], {
|
|
284
288
|
orgId: orgOverride,
|
|
285
289
|
tenantId: tenantOverride,
|
|
286
290
|
}, { encryptDoc, decryptDoc })
|
|
291
|
+
mergeUpsertIndexBatchResults(writeTotals, chunkResult)
|
|
287
292
|
|
|
288
|
-
processed +=
|
|
293
|
+
processed += chunkResult.written
|
|
294
|
+
fetched += chunk.length
|
|
289
295
|
cursorOffset += chunk.length
|
|
290
296
|
if (remaining !== undefined) remaining -= chunk.length
|
|
291
297
|
bar.update(processed)
|
|
@@ -296,6 +302,8 @@ async function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<R
|
|
|
296
302
|
bar.update(processed)
|
|
297
303
|
}
|
|
298
304
|
bar.complete()
|
|
305
|
+
// After bar.complete() so the terminal is left in a sane state before we throw.
|
|
306
|
+
assertIndexBatchWritesLanded(entityType, writeTotals)
|
|
299
307
|
return { processed, matched: intended }
|
|
300
308
|
}
|
|
301
309
|
|
|
@@ -23,7 +23,7 @@ type Translator = (key: string, params?: Record<string, string | number>) => str
|
|
|
23
23
|
type PartitionStatus = {
|
|
24
24
|
partitionIndex: number | null
|
|
25
25
|
partitionCount: number | null
|
|
26
|
-
status: 'reindexing' | 'purging' | 'stalled' | 'completed'
|
|
26
|
+
status: 'reindexing' | 'purging' | 'stalled' | 'completed' | 'failed'
|
|
27
27
|
processedCount?: number | null
|
|
28
28
|
totalCount?: number | null
|
|
29
29
|
heartbeatAt?: string | null
|
|
@@ -32,7 +32,7 @@ type PartitionStatus = {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
type JobStatus = {
|
|
35
|
-
status: 'idle' | 'reindexing' | 'purging' | 'stalled'
|
|
35
|
+
status: 'idle' | 'reindexing' | 'purging' | 'stalled' | 'failed'
|
|
36
36
|
startedAt?: string | null
|
|
37
37
|
finishedAt?: string | null
|
|
38
38
|
heartbeatAt?: string | null
|
|
@@ -40,7 +40,7 @@ type JobStatus = {
|
|
|
40
40
|
totalCount?: number | null
|
|
41
41
|
partitions?: PartitionStatus[]
|
|
42
42
|
scope?: {
|
|
43
|
-
status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | null
|
|
43
|
+
status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | 'failed' | null
|
|
44
44
|
processedCount?: number | null
|
|
45
45
|
totalCount?: number | null
|
|
46
46
|
} | null
|
|
@@ -90,6 +90,7 @@ function translateJobStatus(t: Translator, status: JobStatus['status'] | undefin
|
|
|
90
90
|
if (status === 'reindexing') return t('query_index.table.status.reindexing')
|
|
91
91
|
if (status === 'purging') return t('query_index.table.status.purging')
|
|
92
92
|
if (status === 'stalled') return t('query_index.table.status.stalled')
|
|
93
|
+
if (status === 'failed') return t('query_index.table.status.failed')
|
|
93
94
|
return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -100,6 +101,7 @@ function translateScopeStatus(
|
|
|
100
101
|
if (status === 'reindexing') return t('query_index.table.status.scope.reindexing')
|
|
101
102
|
if (status === 'purging') return t('query_index.table.status.scope.purging')
|
|
102
103
|
if (status === 'stalled') return t('query_index.table.status.scope.stalled')
|
|
104
|
+
if (status === 'failed') return t('query_index.table.status.scope.failed')
|
|
103
105
|
return t('query_index.table.status.scope.completed')
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -158,6 +160,7 @@ function createColumns(t: Translator): ColumnDef<Row>[] {
|
|
|
158
160
|
const job = record.job
|
|
159
161
|
const partitions = job?.partitions ?? []
|
|
160
162
|
const ok = record.ok && (!job || job.status === 'idle')
|
|
163
|
+
const jobFailed = job?.status === 'failed'
|
|
161
164
|
const statusText = translateJobStatus(t, job?.status, ok)
|
|
162
165
|
const jobProgress = job ? formatProgressLabel(job.processedCount ?? null, job.totalCount ?? null, t) : null
|
|
163
166
|
const label = jobProgress
|
|
@@ -165,7 +168,7 @@ function createColumns(t: Translator): ColumnDef<Row>[] {
|
|
|
165
168
|
: statusText
|
|
166
169
|
let variant: StatusBadgeVariant = 'neutral'
|
|
167
170
|
if (job) {
|
|
168
|
-
if (job.status === 'stalled') variant = 'error'
|
|
171
|
+
if (job.status === 'stalled' || jobFailed) variant = 'error'
|
|
169
172
|
else if (job.status === 'reindexing' || job.status === 'purging') variant = 'warning'
|
|
170
173
|
else variant = ok ? 'success' : 'neutral'
|
|
171
174
|
} else {
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"query_index.table.logs.viewDetails": "Details anzeigen",
|
|
47
47
|
"query_index.table.refresh": "Aktualisieren",
|
|
48
48
|
"query_index.table.searchPlaceholder": "Nach Entität filtern",
|
|
49
|
+
"query_index.table.status.failed": "Fehlgeschlagen",
|
|
49
50
|
"query_index.table.status.in_sync": "Synchron",
|
|
50
51
|
"query_index.table.status.out_of_sync": "Nicht synchron",
|
|
51
52
|
"query_index.table.status.partitionLabel": "Partition {{index}}",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"query_index.table.status.purging": "Bereinigung",
|
|
55
56
|
"query_index.table.status.reindexing": "Reindizierung",
|
|
56
57
|
"query_index.table.status.scope.completed": "Abgeschlossen",
|
|
58
|
+
"query_index.table.status.scope.failed": "Fehlgeschlagen",
|
|
57
59
|
"query_index.table.status.scope.purging": "Bereinigung",
|
|
58
60
|
"query_index.table.status.scope.reindexing": "Läuft",
|
|
59
61
|
"query_index.table.status.scope.stalled": "Angehalten",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"query_index.table.logs.viewDetails": "View details",
|
|
47
47
|
"query_index.table.refresh": "Refresh",
|
|
48
48
|
"query_index.table.searchPlaceholder": "Filter by entity",
|
|
49
|
+
"query_index.table.status.failed": "Failed",
|
|
49
50
|
"query_index.table.status.in_sync": "In sync",
|
|
50
51
|
"query_index.table.status.out_of_sync": "Out of sync",
|
|
51
52
|
"query_index.table.status.partitionLabel": "Partition {{index}}",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"query_index.table.status.purging": "Purging",
|
|
55
56
|
"query_index.table.status.reindexing": "Reindexing",
|
|
56
57
|
"query_index.table.status.scope.completed": "Done",
|
|
58
|
+
"query_index.table.status.scope.failed": "Failed",
|
|
57
59
|
"query_index.table.status.scope.purging": "Purging",
|
|
58
60
|
"query_index.table.status.scope.reindexing": "Running",
|
|
59
61
|
"query_index.table.status.scope.stalled": "Stalled",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"query_index.table.logs.viewDetails": "Ver detalles",
|
|
47
47
|
"query_index.table.refresh": "Actualizar",
|
|
48
48
|
"query_index.table.searchPlaceholder": "Filtrar por entidad",
|
|
49
|
+
"query_index.table.status.failed": "Con errores",
|
|
49
50
|
"query_index.table.status.in_sync": "Sincronizado",
|
|
50
51
|
"query_index.table.status.out_of_sync": "Fuera de sincronización",
|
|
51
52
|
"query_index.table.status.partitionLabel": "Partición {{index}}",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"query_index.table.status.purging": "Depurando",
|
|
55
56
|
"query_index.table.status.reindexing": "Reindexando",
|
|
56
57
|
"query_index.table.status.scope.completed": "Completado",
|
|
58
|
+
"query_index.table.status.scope.failed": "Con errores",
|
|
57
59
|
"query_index.table.status.scope.purging": "Depurando",
|
|
58
60
|
"query_index.table.status.scope.reindexing": "Ejecutando",
|
|
59
61
|
"query_index.table.status.scope.stalled": "Detenido",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"query_index.table.logs.viewDetails": "Pokaż szczegóły",
|
|
47
47
|
"query_index.table.refresh": "Odśwież",
|
|
48
48
|
"query_index.table.searchPlaceholder": "Filtruj według encji",
|
|
49
|
+
"query_index.table.status.failed": "Niepowodzenie",
|
|
49
50
|
"query_index.table.status.in_sync": "Zsynchronizowany",
|
|
50
51
|
"query_index.table.status.out_of_sync": "Poza synchronizacją",
|
|
51
52
|
"query_index.table.status.partitionLabel": "Partycja {{index}}",
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
"query_index.table.status.purging": "Czyszczenie",
|
|
55
56
|
"query_index.table.status.reindexing": "Ponowne indeksowanie",
|
|
56
57
|
"query_index.table.status.scope.completed": "Zakończone",
|
|
58
|
+
"query_index.table.status.scope.failed": "Niepowodzenie",
|
|
57
59
|
"query_index.table.status.scope.purging": "Czyszczenie",
|
|
58
60
|
"query_index.table.status.scope.reindexing": "Uruchomione",
|
|
59
61
|
"query_index.table.status.scope.stalled": "Zatrzymane",
|