flush flushes the current batch to the database and pubsub.
(ctx context.Context, reason string)
| 298 | |
| 299 | // flush flushes the current batch to the database and pubsub. |
| 300 | func (b *Batcher) flush(ctx context.Context, reason string) { |
| 301 | count := len(b.batch) |
| 302 | |
| 303 | if count == 0 { |
| 304 | return |
| 305 | } |
| 306 | |
| 307 | start := b.clock.Now() |
| 308 | b.log.Debug(ctx, "flushing metadata batch", |
| 309 | slog.F("reason", reason), |
| 310 | slog.F("count", count), |
| 311 | ) |
| 312 | |
| 313 | // Convert batch map to parallel arrays for the batch query. |
| 314 | // Also build map of agent IDs for per-agent metrics and pubsub. |
| 315 | var ( |
| 316 | agentIDs = make([]uuid.UUID, 0, count) |
| 317 | keys = make([]string, 0, count) |
| 318 | values = make([]string, 0, count) |
| 319 | errors = make([]string, 0, count) |
| 320 | collectedAt = make([]time.Time, 0, count) |
| 321 | agentKeys = make(map[uuid.UUID]int) // Track keys per agent for metrics |
| 322 | ) |
| 323 | |
| 324 | for ck, mv := range b.batch { |
| 325 | agentIDs = append(agentIDs, ck.agentID) |
| 326 | keys = append(keys, ck.key) |
| 327 | values = append(values, mv.v) |
| 328 | errors = append(errors, mv.error) |
| 329 | collectedAt = append(collectedAt, mv.collectedAt) |
| 330 | agentKeys[ck.agentID]++ |
| 331 | } |
| 332 | |
| 333 | // Batch has been processed into slices for our DB request, so we can clear it. |
| 334 | // It's safe to clear before we know whether the flush is successful as agent metadata is not critical, and therefore |
| 335 | // we do not retry failed flushes and losing a batch of metadata is okay. |
| 336 | b.batch = make(map[compositeKey]value) |
| 337 | b.currentBatchLen.Store(0) |
| 338 | |
| 339 | // Record per-agent utilization metrics. |
| 340 | for _, keyCount := range agentKeys { |
| 341 | b.Metrics.BatchUtilization.Observe(float64(keyCount)) |
| 342 | } |
| 343 | |
| 344 | // Update the database with all metadata updates in a single query. |
| 345 | err := b.store.BatchUpdateWorkspaceAgentMetadata(ctx, database.BatchUpdateWorkspaceAgentMetadataParams{ |
| 346 | WorkspaceAgentID: agentIDs, |
| 347 | Key: keys, |
| 348 | Value: values, |
| 349 | Error: errors, |
| 350 | CollectedAt: collectedAt, |
| 351 | }) |
| 352 | elapsed := b.clock.Since(start) |
| 353 | |
| 354 | if err != nil { |
| 355 | if database.IsQueryCanceledError(err) { |
| 356 | b.log.Debug(ctx, "query canceled, skipping update of workspace agent metadata", slog.F("elapsed", elapsed)) |
| 357 | return |
no test coverage detected