65 lines
2.3 KiB
Go
65 lines
2.3 KiB
Go
package kmsvc
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
kafkamgmtv1 "forgejo.riotpiao.homelab.com/rock/kmsvc-proto/gen/kafkamgmt/v1"
|
||
|
|
)
|
||
|
|
|
||
|
|
// MaxReceiveMessages mirrors the server-side cap (design.md §2b).
|
||
|
|
const MaxReceiveMessages = 10
|
||
|
|
|
||
|
|
// MaxWaitTimeSeconds mirrors the server-side long-poll cap (design.md §2b).
|
||
|
|
const MaxWaitTimeSeconds = 20
|
||
|
|
|
||
|
|
// ReceiveOptions configures ReceiveMessage.
|
||
|
|
type ReceiveOptions struct {
|
||
|
|
// MaxNumberOfMessages caps how many messages are returned (1-10).
|
||
|
|
MaxNumberOfMessages int32
|
||
|
|
// WaitTimeSeconds requests SQS-style long polling (0-20). The server
|
||
|
|
// blocks up to this long before returning an empty result.
|
||
|
|
WaitTimeSeconds int32
|
||
|
|
// VisibilityTimeoutSeconds overrides the queue's default visibility
|
||
|
|
// timeout for the returned messages, if non-zero.
|
||
|
|
VisibilityTimeoutSeconds int32
|
||
|
|
}
|
||
|
|
|
||
|
|
// ReceiveMessage long-polls queueName for up to opts.WaitTimeSeconds before
|
||
|
|
// returning, then returns whatever messages (zero or more) are available.
|
||
|
|
//
|
||
|
|
// At-least-once delivery: a message may be redelivered (e.g. after the
|
||
|
|
// caller's visibility timeout expires without DeleteMessage) — callers must
|
||
|
|
// be idempotent or dedup on MessageID/MessageGroupID as appropriate.
|
||
|
|
//
|
||
|
|
// ctx's deadline is extended internally by a small margin beyond
|
||
|
|
// WaitTimeSeconds so a slow network round trip doesn't truncate a poll that
|
||
|
|
// the server was about to satisfy; this margin never extends the result
|
||
|
|
// beyond what the caller's own ctx allows if ctx is already deadlined sooner.
|
||
|
|
func (c *Client) ReceiveMessage(ctx context.Context, queueName string, opts ReceiveOptions) ([]Message, error) {
|
||
|
|
callCtx := ctx
|
||
|
|
if opts.WaitTimeSeconds > 0 {
|
||
|
|
margin := 5 * time.Second
|
||
|
|
deadline := time.Now().Add(time.Duration(opts.WaitTimeSeconds)*time.Second + margin)
|
||
|
|
var cancel context.CancelFunc
|
||
|
|
callCtx, cancel = context.WithDeadline(ctx, deadline)
|
||
|
|
defer cancel()
|
||
|
|
}
|
||
|
|
|
||
|
|
resp, err := c.stub.ReceiveMessage(callCtx, &kafkamgmtv1.ReceiveMessageRequest{
|
||
|
|
QueueName: queueName,
|
||
|
|
MaxNumberOfMessages: opts.MaxNumberOfMessages,
|
||
|
|
WaitTimeSeconds: opts.WaitTimeSeconds,
|
||
|
|
VisibilityTimeoutSeconds: opts.VisibilityTimeoutSeconds,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
return nil, mapError(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
out := make([]Message, 0, len(resp.Messages))
|
||
|
|
for _, m := range resp.Messages {
|
||
|
|
out = append(out, toMessage(m))
|
||
|
|
}
|
||
|
|
return out, nil
|
||
|
|
}
|