实现预分配 RunnerService facade

This commit is contained in:
2026-09-20 19:51:32 +00:00
parent b77245e4b9
commit 5fdd39f7ff
9 changed files with 481 additions and 7 deletions
+29 -5
View File
@@ -52,6 +52,11 @@ type Accepter interface {
Accept(context.Context, taskassignment.Assignment) (bool, error)
}
type Claims interface {
Offer(taskassignment.Assignment) (<-chan struct{}, error)
WaitClaimed(context.Context, string) error
}
// Message is the subset of jetstream.Msg needed by one reconciliation.
type Message interface {
Data() []byte
@@ -62,19 +67,24 @@ type Message interface {
// Processor maps one delivery to one idempotent worker reconciliation.
type Processor struct {
TrustDomain string
Accepter Accepter
RetryDelay time.Duration
TrustDomain string
Accepter Accepter
Claims Claims
RetryDelay time.Duration
ClaimTimeout time.Duration
}
func (p Processor) Process(ctx context.Context, message Message) error {
if p.Accepter == nil {
return errors.New("assignment accepter is required")
if p.Accepter == nil || p.Claims == nil {
return errors.New("assignment accepter and claim registry are required")
}
assignment, err := taskassignment.Unmarshal(message.Data(), p.TrustDomain)
if err != nil {
return errors.Join(err, message.TermWithReason("invalid assignment"))
}
if _, err := p.Claims.Offer(assignment); err != nil {
return errors.Join(err, message.TermWithReason("conflicting assignment"))
}
accepted, err := p.Accepter.Accept(ctx, assignment)
if err != nil {
delay := p.RetryDelay
@@ -84,6 +94,20 @@ func (p Processor) Process(ctx context.Context, message Message) error {
return errors.Join(err, message.NakWithDelay(delay))
}
if accepted {
timeout := p.ClaimTimeout
if timeout <= 0 {
timeout = 4 * time.Minute
}
claimContext, cancel := context.WithTimeout(ctx, timeout)
err := p.Claims.WaitClaimed(claimContext, assignment.ID)
cancel()
if err != nil {
delay := p.RetryDelay
if delay <= 0 {
delay = 2 * time.Second
}
return errors.Join(err, message.NakWithDelay(delay))
}
if err := message.DoubleAck(ctx); err != nil {
return fmt.Errorf("ack assignment %s: %w", assignment.ID, err)
}