fix(feedback): address backend review gaps

This commit is contained in:
ZiyaZhang
2026-08-10 21:18:45 -07:00
parent c3d0fe1bf9
commit c61be60737
20 changed files with 893 additions and 16 deletions
@@ -158,6 +158,7 @@ export class MessageFeedbackService extends GatewayService {
private readonly maxNoteBytes: number
private table?: KvTable<SessionId, MessageFeedbackRow>
private readonly operationTails = new Map<SessionId, Promise<void>>()
private mutationAdmissionOpen = true
/**
* @param ctx - Host context carrying persistence and the storage-domain form.
@@ -171,7 +172,11 @@ export class MessageFeedbackService extends GatewayService {
/** Open and own the one message-feedback sidecar domain. */
protected async [Service.init](): Promise<void> {
const domain = await this.ctx.storageDomain.open(messageFeedbackDomainSpec)
this.ctx.effect(() => () => domain.close(), 'message-feedback.domainClose')
this.ctx.effect(() => async () => {
this.mutationAdmissionOpen = false
await Promise.all(this.operationTails.values())
await domain.close()
}, 'message-feedback.domainClose')
this.table = domain.table('sessions')
}
@@ -354,6 +359,9 @@ export class MessageFeedbackService extends GatewayService {
/** Queue a complete read/compare/write mutation behind this Session's prior mutation. */
private enqueue<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T> {
if (!this.mutationAdmissionOpen) {
return Promise.reject(new Error('message-feedback: service is disposing'))
}
const previous = this.operationTails.get(sessionId) ?? Promise.resolve()
const result = previous.then(operation)
const tail = result.then(() => undefined, () => undefined)
@@ -22,6 +22,8 @@ export const messageFeedbackVersionSchema = z.uuid()
.transform(value => value as MessageFeedbackVersion)
/** Runtime schema for one current feedback item. */
// Zod infers transformed branded fields structurally, so it cannot name the
// public interface even though every branded output is created below.
export const messageFeedbackItemSchema = z.object({
messageId: z.string().min(1).transform(value => value as MessageId),
rating: messageFeedbackRatingSchema,