class MessageRep(MessageBase): """ Purpose: respond to a node for any requested message """ # TODO: support a setter for `msg` to create an instance of a type # according to `msg_type` typename = MESSAGE_RESPONSE schema = ((f.MSG_TYPE.nm, ChooseField(values=MessageReq.allowed_types)), (f.PARAMS.nm, AnyMapField()), (f.MSG.nm, AnyField()))
class CurrentState(MessageBase): """ Node sends this kind of message for nodes which suddenly reconnected (lagged). It contains information about current pool state, like view no, primary etc. """ typename = CURRENT_STATE schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.PRIMARY.nm, IterableField(AnyField())), # ViewChangeDone )
class NewView(MessageBase): typename = NEW_VIEW schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.VIEW_CHANGES.nm, IterableField(ViewChangeField()) ), # list of tuples (node_name, view_change_digest) (f.CHECKPOINT.nm, AnyField()), # Checkpoint to be selected as stable (TODO: or tuple?) (f.BATCHES.nm, IterableField(BatchIDField()) ) # list of tuples (view_no, pp_seq_no, pp_digest) # that should get into new view )
class ViewChange(MessageBase): typename = VIEW_CHANGE schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.STABLE_CHECKPOINT.nm, NonNegativeNumberField()), (f.PREPARED.nm, IterableField( BatchIDField())), # list of tuples (view_no, pp_seq_no, pp_digest) (f.PREPREPARED.nm, IterableField( BatchIDField())), # list of tuples (view_no, pp_seq_no, pp_digest) (f.CHECKPOINTS.nm, IterableField(AnyField()) ) # list of Checkpoints TODO: should we change to tuples? )
class ViewChange(MessageBase): typename = VIEW_CHANGE schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.STABLE_CHECKPOINT.nm, NonNegativeNumberField()), (f.PREPARED.nm, IterableField(BatchIDField())), # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) (f.PREPREPARED.nm, IterableField(BatchIDField())), # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) (f.CHECKPOINTS.nm, IterableField(AnyField())) # list of Checkpoints TODO: should we change to tuples? ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) checkpoints = [] for chk in self.checkpoints: if isinstance(chk, dict): checkpoints.append(Checkpoint(**chk)) if checkpoints: self.checkpoints = checkpoints # The field `prepared` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we need to deserialize it. if self.prepared and isinstance(self.prepared[0], dict): self.prepared = [BatchID(**bid) for bid in self.prepared if isinstance(bid, dict)] # The field `preprepared` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we need to deserialize it. if self.preprepared and isinstance(self.preprepared[0], dict): self.preprepared = [BatchID(**bid) for bid in self.preprepared if isinstance(bid, dict)] def _asdict(self): result = super()._asdict() checkpoints = [] for chk in self.checkpoints: if isinstance(chk, dict): continue checkpoints.append(chk._asdict()) if checkpoints: result[f.CHECKPOINTS.nm] = checkpoints # The field `prepared` can to be a list of BatchIDs or of dicts. # If its a list of BatchID then we need to serialize it. if self.prepared and isinstance(self.prepared[0], BatchID): result[f.PREPARED.nm] = [bid._asdict() for bid in self.prepared] # The field `preprepared` can to be a list of BatchIDs or of dicts. # If its a list of BatchID then we need to serialize it. if self.preprepared and isinstance(self.preprepared[0], BatchID): result[f.PREPREPARED.nm] = [bid._asdict() for bid in self.preprepared] return result
class ConstraintListField(MessageValidator): schema = ((CONSTRAINT_ID, ChooseField(values=ConstraintsEnum.values())), (AUTH_CONSTRAINTS, IterableField(AnyField()))) def _validate_message(self, val): constraints = val.get(AUTH_CONSTRAINTS) if not constraints: self._raise_invalid_message("Fields {} should not be an empty " "list.".format(AUTH_CONSTRAINTS)) for constraint in constraints: error_msg = ConstraintField(ConstraintEntityField(), self).validate(constraint) if error_msg: self._raise_invalid_message(error_msg)
class NewView(MessageBase): typename = NEW_VIEW schema = ( (f.VIEW_NO.nm, NonNegativeNumberField()), (f.VIEW_CHANGES.nm, IterableField(ViewChangeField()) ), # list of tuples (node_name, view_change_digest) (f.CHECKPOINT.nm, AnyField()), # Checkpoint to be selected as stable (TODO: or tuple?) (f.BATCHES.nm, IterableField(BatchIDField()) ), # list of tuples (view_no, pp_view_no, pp_seq_no, pp_digest) (f.PRIMARY.nm, LimitedLengthStringField(optional=True)) # that should get into new view ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if isinstance(self.checkpoint, dict): self.checkpoint = Checkpoint(**self.checkpoint) # The field `batches` can to be a list of BatchIDs or of dicts. # If it's not a list of dicts then we don't need to deserialize it. if not self.batches or not isinstance(self.batches[0], dict): return self.batches = [ BatchID(**bid) for bid in self.batches if isinstance(bid, dict) ] def _asdict(self): result = super()._asdict() chk = self.checkpoint if not isinstance(chk, dict): result[f.CHECKPOINT.nm] = chk._asdict() # The field `batches` can to be a list of BatchIDs or of dicts. # If its a list of dicts then we don't need to serialize it. if not self.batches or not isinstance(self.batches[0], BatchID): return result result[f.BATCHES.nm] = [bid._asdict() for bid in self.batches] return result
class OldViewPrePrepareReply(MessageBase): typename = OLD_VIEW_PREPREPARE_REP schema = ( (f.INST_ID.nm, NonNegativeNumberField()), (f.PREPREPARES.nm, IterableField(AnyField())), )