File size: 1,191 Bytes
795f737 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | """Task replacement and execution share a lock; queued old actions are rejected."""
from threading import RLock
from uuid import uuid4
from .actions import Ticket
class Rejected(ValueError):
pass
class Authority:
def __init__(self):
self.lock = RLock()
self.session_id = uuid4().hex
self.task_id = ""
self.epoch = 0
self.sequence = 0
self.goal = ""
def replace(self, goal):
if not isinstance(goal, str) or not goal.strip():
raise ValueError("task needs a nonempty goal")
with self.lock:
self.task_id = uuid4().hex
self.epoch += 1
self.sequence = 0
self.goal = goal
def ticket(self, state):
with self.lock:
if not self.task_id:
raise Rejected("NO_TASK")
return Ticket(self.session_id, self.task_id, self.epoch, self.sequence,
state.document_id, state.revision, state.state_hash)
def validate(self, ticket, state):
if ticket != self.ticket(state):
raise Rejected("STALE_AUTHORITY_OR_OBSERVATION")
def consume(self):
self.sequence += 1
|