feat: serialize keyed tasks across queues with durable fencing tokens
This commit is contained in:
@@ -50,12 +50,13 @@ func (s *ExecutionStore) transaction(ctx context.Context, token auth.Token, acti
|
||||
}
|
||||
|
||||
type sessionState struct {
|
||||
queue core.ID
|
||||
capacity uint32
|
||||
sequence uint64
|
||||
draining bool
|
||||
expires time.Time
|
||||
capabilities []worker.Capability
|
||||
queue core.ID
|
||||
capacity uint32
|
||||
sequence uint64
|
||||
draining bool
|
||||
expires time.Time
|
||||
capabilities []worker.Capability
|
||||
concurrencyKeys bool
|
||||
}
|
||||
|
||||
func (s *ExecutionStore) welcome(b worker.Binding, state sessionState, now time.Time) worker.Welcome {
|
||||
@@ -69,9 +70,10 @@ func (s *ExecutionStore) Connect(ctx context.Context, token auth.Token, in worke
|
||||
return binding, out, err
|
||||
}
|
||||
registration, err := requestDigest(struct {
|
||||
Queue core.ID
|
||||
Capabilities []worker.Capability
|
||||
}{in.QueueID, in.Capabilities})
|
||||
Queue core.ID
|
||||
Capabilities []worker.Capability
|
||||
ConcurrencyKeys bool `json:"ConcurrencyKeys,omitempty"`
|
||||
}{in.QueueID, in.Capabilities, in.ConcurrencyKeys})
|
||||
if err != nil {
|
||||
return binding, out, err
|
||||
}
|
||||
@@ -116,12 +118,12 @@ func (s *ExecutionStore) Connect(ctx context.Context, token auth.Token, in worke
|
||||
return err
|
||||
}
|
||||
binding = worker.Binding{InstanceID: in.InstanceID, SessionID: session, Epoch: epoch + 1, Proof: proof}
|
||||
state := sessionState{queue: in.QueueID, capacity: in.Capacity, draining: draining, expires: now.Add(s.options.SessionTTL), capabilities: in.Capabilities}
|
||||
state := sessionState{queue: in.QueueID, capacity: in.Capacity, draining: draining, expires: now.Add(s.options.SessionTTL), capabilities: in.Capabilities, concurrencyKeys: in.ConcurrencyKeys}
|
||||
caps, err := json.Marshal(in.Capabilities)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO pulse_worker_sessions(namespace_id,id,worker_instance_id,credential_id,node_id,session_epoch,capabilities,capacity,draining,expires_at) VALUES (?,?,?,?,?,?,?,?,?,?)`, token.NamespaceID, session, in.InstanceID, token.CredentialID, s.node, binding.Epoch, string(caps), in.Capacity, draining, state.expires)
|
||||
_, err = tx.ExecContext(ctx, `INSERT INTO pulse_worker_sessions(namespace_id,id,worker_instance_id,credential_id,node_id,session_epoch,capabilities,capacity,draining,expires_at,concurrency_keys) VALUES (?,?,?,?,?,?,?,?,?,?,?)`, token.NamespaceID, session, in.InstanceID, token.CredentialID, s.node, binding.Epoch, string(caps), in.Capacity, draining, state.expires, in.ConcurrencyKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -172,7 +174,7 @@ func (s *ExecutionStore) lockSession(ctx context.Context, tx *sql.Tx, token auth
|
||||
var node, instance, sessionCredential core.ID
|
||||
var sessionEpoch uint64
|
||||
var raw []byte
|
||||
err = tx.QueryRowContext(ctx, `SELECT node_id,worker_instance_id,credential_id,session_epoch,capacity,capacity_sequence,capabilities,expires_at FROM pulse_worker_sessions WHERE namespace_id=? AND id=? FOR UPDATE`, token.NamespaceID, b.SessionID).Scan(&node, &instance, &sessionCredential, &sessionEpoch, &state.capacity, &state.sequence, &raw, &state.expires)
|
||||
err = tx.QueryRowContext(ctx, `SELECT node_id,worker_instance_id,credential_id,session_epoch,capacity,capacity_sequence,capabilities,expires_at,concurrency_keys FROM pulse_worker_sessions WHERE namespace_id=? AND id=? FOR UPDATE`, token.NamespaceID, b.SessionID).Scan(&node, &instance, &sessionCredential, &sessionEpoch, &state.capacity, &state.sequence, &raw, &state.expires, &state.concurrencyKeys)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return state, worker.StaleSession
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user