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