MCPcopy
hub / github.com/coder/mux / migrateWorkspaceId

Method migrateWorkspaceId

src/node/services/historyService.ts:2000–2050  ·  view source on GitHub ↗

* Migrate all messages in chat.jsonl to use a new workspace ID * This is used during workspace rename to update the workspaceId field in all historical messages * IMPORTANT: Should be called AFTER the session directory has been renamed

(oldWorkspaceId: string, newWorkspaceId: string)

Source from the content-addressed store, hash-verified

1998 * IMPORTANT: Should be called AFTER the session directory has been renamed
1999 */
2000 async migrateWorkspaceId(oldWorkspaceId: string, newWorkspaceId: string): Promise<Result<void>> {
2001 return this.fileLocks.withLock(newWorkspaceId, async () => {
2002 try {
2003 // Migrate the sealed archive first so a crash mid-migration never leaves
2004 // the active file pointing at a stale-ID archive.
2005 const archiveMessages = await this.readArchivedHistory(newWorkspaceId);
2006 if (archiveMessages.length > 0) {
2007 await writeFileAtomic(
2008 this.getChatArchivePath(newWorkspaceId),
2009 this.serializeHistoryEntries(archiveMessages, newWorkspaceId)
2010 );
2011 }
2012
2013 // Read messages from the NEW workspace location (directory was already renamed).
2014 // Structural rewrite requires full file content.
2015 const messages = await this.readChatHistory(newWorkspaceId);
2016 if (messages.length === 0) {
2017 // No active messages to migrate, just transfer the sequence counter.
2018 // Floor it with the archive max: an archive-only session (active file
2019 // deleted/truncated) renamed in a fresh process has no cached counter,
2020 // and seeding 0 would reuse archived historySequence values.
2021 const oldCounter = this.sequenceCounters.get(oldWorkspaceId) ?? 0;
2022 const archiveFloor = (await this.getArchiveTailMaxSequence(newWorkspaceId)) + 1;
2023 this.sequenceCounters.set(newWorkspaceId, Math.max(oldCounter, archiveFloor));
2024 this.sequenceCounters.delete(oldWorkspaceId);
2025 return Ok(undefined);
2026 }
2027
2028 // Rewrite all messages with new workspace ID
2029 const newHistoryPath = this.getChatHistoryPath(newWorkspaceId);
2030 const historyEntries = this.serializeHistoryEntries(messages, newWorkspaceId);
2031
2032 // Atomic write prevents corruption if app crashes mid-write
2033 await writeFileAtomic(newHistoryPath, historyEntries);
2034
2035 // Transfer sequence counter to new workspace ID
2036 const oldCounter = this.sequenceCounters.get(oldWorkspaceId) ?? 0;
2037 this.sequenceCounters.set(newWorkspaceId, oldCounter);
2038 this.sequenceCounters.delete(oldWorkspaceId);
2039
2040 log.debug(
2041 `Migrated ${messages.length} messages from ${oldWorkspaceId} to ${newWorkspaceId}`
2042 );
2043
2044 return Ok(undefined);
2045 } catch (error) {
2046 const message = getErrorMessage(error);
2047 return Err(`Failed to migrate workspace ID: ${message}`);
2048 }
2049 });
2050 }
2051}

Callers 1

Calls 14

readArchivedHistoryMethod · 0.95
getChatArchivePathMethod · 0.95
readChatHistoryMethod · 0.95
getChatHistoryPathMethod · 0.95
OkFunction · 0.90
getErrorMessageFunction · 0.90
ErrFunction · 0.90
withLockMethod · 0.80
setMethod · 0.80
debugMethod · 0.80

Tested by

no test coverage detected