Skip to content

Commit 05f6a60

Browse files
author
Eric Wheeler
committed
refactor: make say() transactional
Refactors the say() method in Task.ts to ensure message updates are atomic. The mutation logic for the last message is moved inside the modifyClineMessages() callback. This makes the find, update, and save operations a single atomic transaction, preventing race conditions and ensuring data integrity. Signed-off-by: Eric Wheeler <[email protected]>
1 parent a083893 commit 05f6a60

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

src/core/task/Task.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,13 @@ export class Task extends EventEmitter<ClineEvents> {
726726
}
727727

728728
if (partial !== undefined) {
729-
const lastMessage = this.clineMessages.at(-1)
729+
let lastMessage = this.clineMessages.at(-1)
730+
731+
if (lastMessage === undefined) {
732+
throw new Error(
733+
`[RooCode#say] task ${this.taskId}.${this.instanceId}: clineMessages is empty? Please report this bug.`,
734+
)
735+
}
730736

731737
const isUpdatingPreviousPartial =
732738
lastMessage && lastMessage.partial && lastMessage.type === "say" && lastMessage.say === type
@@ -762,23 +768,25 @@ export class Task extends EventEmitter<ClineEvents> {
762768
// This is the complete version of a previously partial
763769
// message, so replace the partial with the complete version.
764770
if (isUpdatingPreviousPartial) {
765-
if (!options.isNonInteractive) {
766-
this.lastMessageTs = lastMessage.ts
767-
}
768-
769-
lastMessage.text = text
770-
lastMessage.images = images
771-
lastMessage.partial = false
772-
lastMessage.progressStatus = progressStatus
773-
774771
// Instead of streaming partialMessage events, we do a save
775772
// and post like normal to persist to disk.
776-
await this.modifyClineMessages(async () => {
777-
return this.clineMessages
778-
})
773+
await this.modifyClineMessages(async (messages) => {
774+
lastMessage = messages.at(-1) // update ref for transaction
775+
if (lastMessage) {
776+
if (!options.isNonInteractive) {
777+
this.lastMessageTs = lastMessage.ts
778+
}
779779

780-
// More performant than an entire `postStateToWebview`.
781-
this.updateClineMessage(lastMessage)
780+
lastMessage.text = text
781+
lastMessage.images = images
782+
lastMessage.partial = false
783+
lastMessage.progressStatus = progressStatus
784+
785+
// More performant than an entire `postStateToWebview`.
786+
this.updateClineMessage(lastMessage)
787+
}
788+
return messages
789+
})
782790
} else {
783791
// This is a new and complete message, so add it like normal.
784792
const sayTs = Date.now()

0 commit comments

Comments
 (0)