mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
e195856c43
--------- Signed-off-by: Callum Styan <callumstyan@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package metadatabatcher
|
|
|
|
import (
|
|
"encoding/base64"
|
|
|
|
"github.com/google/uuid"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
const (
|
|
// uuidBase64Size is the size of a base64-encoded UUID without padding (22 characters).
|
|
UUIDBase64Size = 22
|
|
|
|
// maxAgentIDsPerChunk is the maximum number of agent IDs that can fit in a
|
|
// single pubsub message. PostgreSQL NOTIFY has an 8KB limit.
|
|
// With base64 encoding, each UUID is 22 characters, so we can fit
|
|
// ~363 agent IDs per chunk (8000 / 22 = 363.6).
|
|
maxAgentIDsPerChunk = maxPubsubPayloadSize / UUIDBase64Size
|
|
)
|
|
|
|
func EncodeAgentID(agentID uuid.UUID, dst []byte) error {
|
|
// Encode UUID bytes to base64 without padding (RawStdEncoding).
|
|
// This produces exactly 22 characters per UUID.
|
|
reqLen := base64.RawStdEncoding.EncodedLen(len(agentID))
|
|
if len(dst) < reqLen {
|
|
return xerrors.Errorf("destination byte slice was too small %d, required %d", len(dst), reqLen)
|
|
}
|
|
base64.RawStdEncoding.Encode(dst, agentID[:])
|
|
return nil
|
|
}
|
|
|
|
// EncodeAgentIDChunks encodes agent IDs into chunks that fit within the
|
|
// PostgreSQL NOTIFY 8KB payload size limit. Each UUID is base64-encoded
|
|
// (without padding) and concatenated into a single byte slice per chunk.
|
|
func EncodeAgentIDChunks(agentIDs []uuid.UUID) ([][]byte, error) {
|
|
chunks := make([][]byte, 0, (len(agentIDs)+maxAgentIDsPerChunk-1)/maxAgentIDsPerChunk)
|
|
|
|
for i := 0; i < len(agentIDs); i += maxAgentIDsPerChunk {
|
|
end := i + maxAgentIDsPerChunk
|
|
if end > len(agentIDs) {
|
|
end = len(agentIDs)
|
|
}
|
|
|
|
chunk := agentIDs[i:end]
|
|
|
|
// Build payload by base64-encoding each UUID (without padding) and
|
|
// concatenating them. This is UTF-8 safe for PostgreSQL NOTIFY.
|
|
payload := make([]byte, len(chunk)*UUIDBase64Size)
|
|
for i, agentID := range chunk {
|
|
err := EncodeAgentID(agentID, payload[i*UUIDBase64Size:(i+1)*UUIDBase64Size])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
chunks = append(chunks, payload)
|
|
}
|
|
|
|
return chunks, nil
|
|
}
|