Skip to content

Commit 4e18d6a

Browse files
committed
refactor: separate discovered totals from flush deltas in LocalProgress
LocalProgress no longer carries bytesTotal/filesTotal — those are passed separately from ctx.discovered. Pending state reset uses emptyLocalProgress() instead of manual field-by-field assignment.
1 parent 11a9b06 commit 4e18d6a

3 files changed

Lines changed: 19 additions & 25 deletions

File tree

src/migration.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { Logger } from 'pino'
22
import type { StackClient } from './stack-client.js'
3-
import type { MigrationCommand, TrackingError, TrackingSkipped } from './types.js'
3+
import type { MigrationCommand } from './types.js'
44
import {
55
setRunning,
66
setCompleted,
77
setFailed,
88
flushProgress,
9+
emptyLocalProgress,
910
isConflictError,
1011
type LocalProgress,
1112
} from './tracking.js'
@@ -43,15 +44,8 @@ async function flush(ctx: MigrationContext): Promise<void> {
4344
if (ctx.filesSinceFlush === 0 && ctx.pending.errors.length === 0 && ctx.pending.skipped.length === 0) {
4445
return
4546
}
46-
await flushProgress(ctx.stackClient, ctx.command.migrationId, {
47-
...ctx.pending,
48-
bytesTotal: ctx.discovered.bytesTotal,
49-
filesTotal: ctx.discovered.filesTotal,
50-
})
51-
ctx.pending.bytesImported = 0
52-
ctx.pending.filesImported = 0
53-
ctx.pending.errors = []
54-
ctx.pending.skipped = []
47+
await flushProgress(ctx.stackClient, ctx.command.migrationId, ctx.pending, ctx.discovered)
48+
ctx.pending = emptyLocalProgress()
5549
ctx.filesSinceFlush = 0
5650
}
5751

@@ -167,7 +161,7 @@ export async function runMigration(
167161
logger: migrationLogger,
168162
discovered: { bytesTotal: 0, filesTotal: 0 },
169163
transferred: { bytes: 0, files: 0 },
170-
pending: { bytesImported: 0, filesImported: 0, bytesTotal: 0, filesTotal: 0, errors: [], skipped: [] },
164+
pending: emptyLocalProgress(),
171165
totalErrors: 0,
172166
totalSkipped: 0,
173167
filesSinceFlush: 0,

src/tracking.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,36 +97,39 @@ export async function setFailed(
9797
}))
9898
}
9999

100-
/** Local progress state accumulated between flushes. */
100+
/** Local progress deltas accumulated between flushes. */
101101
export interface LocalProgress {
102102
bytesImported: number
103103
filesImported: number
104-
bytesTotal: number
105-
filesTotal: number
106104
errors: TrackingError[]
107105
skipped: TrackingSkipped[]
108106
}
109107

108+
export function emptyLocalProgress(): LocalProgress {
109+
return { bytesImported: 0, filesImported: 0, errors: [], skipped: [] }
110+
}
111+
110112
/**
111113
* Flushes locally accumulated progress to CouchDB in a single write.
112-
* Merges local deltas into the remote doc. On 409, re-reads _rev and
113-
* reapplies the patch (external conflict, not self-conflict).
114+
* On 409, re-reads _rev and reapplies the patch.
114115
* @param stackClient - Stack API client
115116
* @param docId - Tracking document ID
116-
* @param local - Accumulated local progress to merge
117+
* @param local - Accumulated deltas since last flush
118+
* @param discovered - Latest discovered totals (bytes_total, files_total)
117119
*/
118120
export async function flushProgress(
119121
stackClient: StackClient,
120122
docId: string,
121-
local: LocalProgress
123+
local: LocalProgress,
124+
discovered: { bytesTotal: number; filesTotal: number }
122125
): Promise<void> {
123126
await updateTracking(stackClient, docId, (doc) => ({
124127
...doc,
125128
progress: {
126129
bytes_imported: doc.progress.bytes_imported + local.bytesImported,
127130
files_imported: doc.progress.files_imported + local.filesImported,
128-
bytes_total: local.bytesTotal,
129-
files_total: local.filesTotal,
131+
bytes_total: discovered.bytesTotal,
132+
files_total: discovered.filesTotal,
130133
},
131134
errors: [...doc.errors, ...local.errors],
132135
skipped: [...doc.skipped, ...local.skipped],

test/tracking.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,9 @@ describe('flushProgress', () => {
132132
await flushProgress(stack, 'mig-1', {
133133
bytesImported: 500,
134134
filesImported: 3,
135-
bytesTotal: 9000,
136-
filesTotal: 20,
137135
errors: [{ path: '/new.txt', message: 'new error', at: '2024-01-02T00:00:00Z' }],
138136
skipped: [{ path: '/dup.txt', reason: 'already exists', size: 42 }],
139-
})
137+
}, { bytesTotal: 9000, filesTotal: 20 })
140138

141139
const calledDoc = vi.mocked(stack.updateTrackingDoc).mock.calls[0][0]
142140
// Deltas are added to existing values
@@ -158,9 +156,8 @@ describe('flushProgress', () => {
158156

159157
await flushProgress(stack, 'mig-1', {
160158
bytesImported: 100, filesImported: 1,
161-
bytesTotal: 100, filesTotal: 1,
162159
errors: [], skipped: [],
163-
})
160+
}, { bytesTotal: 100, filesTotal: 1 })
164161

165162
// Re-reads doc and reapplies patch
166163
expect(stack.getTrackingDoc).toHaveBeenCalledTimes(2)

0 commit comments

Comments
 (0)