backpack1098B
Convex Community5mo ago
5 replies
backpack1098

Convex Triggers + Aggregates Pattern Question

We're using Convex triggers with TableAggregate to maintain aggregated data. We're encountering a pattern issue with mixing direct DB operations and trigger-wrapped mutations.

Setup:
// itemsTrigger.ts
const triggers = new Triggers<DataModel>()

export const aggregateItemScores = new TableAggregate<...>(
  components.aggregateItemScores, {
    namespace: (doc) => `${doc.groupId}-${doc.typeId}`,
    sumValue: (doc) => doc.amount
  }
)

triggers.register("items", aggregateItemScores.trigger())

export const itemsMutation = customMutation(
  rawMutation,
  customCtx(triggers.wrapDB)
)

export const itemsInternalMutation = customMutation(
  rawInternalMutation,
  customCtx(triggers.wrapDB)
)

Current Problem:
// items.ts
export const updateBatch = itemsMutation({  // <-- Wrapped with trigger
  handler: async (ctx, args) => {
    // Delete existing items
    const existing = await getItems(ctx, args.groupId)
    for (const item of existing) {
      await ctx.db.delete(item._id)  // :white_check_mark: Triggers aggregate update
    }
    
    // Add new items
    for (const newItem of args.items) {
      await ItemsHelper.upsertItem(ctx, {  // :x: Does NOT trigger aggregate
        groupId: args.groupId,
        amount: newItem.amount
      })
    }
  }
})

// Separate wrapped mutation for external calls
export const upsertItem = itemsInternalMutation({
  handler: async (ctx, args) => {
    return await ItemsHelper.upsertItem(ctx, args)  // :white_check_mark: Triggers aggregate
  }
})
Was this page helpful?