feat: implement gRPC server + grpc-gateway wiring (task 9)

Assembles tasks 1/6/7/8 into a runnable cmd/server binary: QueueServiceServer
handlers translating kafkamgmt.v1 proto to internal/core/queue's plain Go
types, a lazy per-queue Kafka consumer registry for ReceiveMessage, and a
Redis-scan-based queue discovery loop that starts a reaper goroutine per
queue (queue lifecycle isn't exposed over gRPC, so this is the server's only
signal). Promotes kmsvc-proto to a direct go.mod dependency.

Handler-level integration tests run against kfake+miniredis (same documented
tradeoff as tasks 5-7's envtest/testcontainers substitution), exercising
send->receive->delete through the real QueueServiceServer implementation.
This commit is contained in:
riotpiaole
2026-06-22 06:30:25 -07:00
parent b3be1f929a
commit 26b6922ad4
7 changed files with 607 additions and 1 deletions
+17
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/redis/go-redis/v9"
@@ -79,3 +80,19 @@ func DeleteQueueMeta(ctx context.Context, rdb *redis.Client, queue string) error
}
return nil
}
// ListQueueNames scans for every queue with a published `kmsvc:queue:` row,
// used by the message-plane server to discover which queues need a reaper
// goroutine (design.md §5) since queue lifecycle isn't exposed over gRPC.
func ListQueueNames(ctx context.Context, rdb *redis.Client) ([]string, error) {
const prefix = "kmsvc:queue:"
var names []string
iter := rdb.Scan(ctx, 0, prefix+"*", 0).Iterator()
for iter.Next(ctx) {
names = append(names, strings.TrimPrefix(iter.Val(), prefix))
}
if err := iter.Err(); err != nil {
return nil, fmt.Errorf("list queue names: %w", err)
}
return names, nil
}