state.py (4815B)
1 # standard imports 2 import logging 3 4 # external imports 5 import shep.persist 6 7 logg = logging.getLogger(__name__) 8 9 10 class Verify: 11 12 def verify(self, state_store, key, from_state, to_state): 13 to_state_name = state_store.name(to_state) 14 m = None 15 try: 16 m = getattr(self, to_state_name) 17 except AttributeError: 18 return None 19 20 r = m(state_store, from_state) 21 if r != None: 22 from_state_name = state_store.name(from_state) 23 r = '{} -> {}: {}'.format(from_state_name, to_state_name, r) 24 25 return r 26 27 28 def INSUFFICIENT_FUNDS(self, state_store, from_state): 29 if from_state & state_store.FINAL: 30 return 'already finalized' 31 if from_state & state_store.IN_NETWORK: 32 return 'already in network' 33 34 35 def UNKNOWN_ERROR(self, state_store, from_state): 36 if from_state & state_store.FINAL: 37 return 'already finalized' 38 if from_state & state_store.RESERVED: 39 return 'not reserved' 40 if from_state & state_store.mask_error: 41 return 'already in error state' 42 43 44 def NODE_ERROR(self, state_store, from_state): 45 if from_state & state_store.FINAL: 46 return 'already finalized' 47 if from_state & state_store.IN_NETWORK: 48 return 'already in network' 49 if not from_state & state_store.RESERVED: 50 return 'not reserved' 51 if from_state & state_store.mask_error: 52 return 'already in error state' 53 54 55 def NETWORK_ERROR(self, state_store, from_state): 56 if from_state & state_store.FINAL: 57 return 'already finalized' 58 if from_state & state_store.IN_NETWORK: 59 return 'already in network' 60 61 62 def OBSOLETE(self, state_store, from_state): 63 if from_state & state_store.FINAL: 64 return 'already finalized' 65 if from_state & state_store.IN_NETWORK: 66 return 'already in network' 67 if from_state & state_store.OBSOLETE: 68 return 'already obsolete' 69 70 71 def MANUAL(self, state_store, from_state): 72 if from_state & state_store.FINAL: 73 return 'already finalized' 74 75 76 def QUEUED(self, state_store, from_state): 77 if from_state & state_store.FINAL: 78 return 'already finalized' 79 if from_state & state_store.IN_NETWORK: 80 if not from_state & state_store.mask_error: 81 return 'not in error state' 82 elif from_state & state_store.mask_error: 83 return 'no first send on error state' 84 85 86 def SENDFAIL(self, state_store, from_state): 87 return self.NODE_ERROR(state_store, from_state) 88 89 90 def FINAL(self, state_store, from_state): 91 if from_state & state_store.FINAL: 92 return 'already finalized' 93 94 95 def _MINEFAIL(self, state_store, from_state): 96 return self.NETWORK_ERROR(state_store, from_state) 97 98 99 def _CANCEL(self, state_store, from_state): 100 if from_state: 101 if from_state & state_store.FINAL: 102 return 'already finalized' 103 if not from_state & (state_store.OBSOLETE | state_store.IN_NETWORK): 104 return 'can only cancel state having OBSOLETE and/or IN_NETWORK' 105 106 107 class Status(shep.persist.PersistedState): 108 109 bits = 12 110 111 def __init__(self, store_factory, allow_invalid=False, event_callback=None): 112 verify = Verify().verify 113 self.set_default_state('PENDING') 114 super(Status, self).__init__(store_factory, self.bits, verifier=verify, check_alias=not allow_invalid, event_callback=event_callback) 115 self.add('QUEUED') 116 self.add('RESERVED') 117 self.add('IN_NETWORK') 118 self.add('DEFERRED') 119 self.add('INSUFFICIENT_FUNDS') 120 self.add('LOCAL_ERROR') 121 self.add('NODE_ERROR') 122 self.add('NETWORK_ERROR') 123 self.add('UNKNOWN_ERROR') 124 self.add('FINAL') 125 self.add('OBSOLETE') 126 self.add('MANUAL') 127 128 self.alias('SENDFAIL', self.DEFERRED | self.LOCAL_ERROR) 129 self.alias('RETRY', self.DEFERRED | self.QUEUED) 130 self.alias('OBSOLETED', self.OBSOLETE | self.IN_NETWORK) 131 self.alias('FUBAR', self.FINAL | self.UNKNOWN_ERROR) 132 self.alias('CANCELLED', self.IN_NETWORK | self.FINAL | self.OBSOLETE) 133 self.alias('OVERRIDDEN', self.FINAL | self.OBSOLETE | self.MANUAL) 134 self.alias('REJECTED', self.NODE_ERROR | self.FINAL) 135 self.alias('REVERTED', self.IN_NETWORK | self.FINAL | self.NETWORK_ERROR) 136 self.alias('SUCCESS', self.IN_NETWORK | self.FINAL) 137 self.alias('_MINEFAIL', self.FINAL | self.NETWORK_ERROR) 138 self.alias('_CANCEL', self.FINAL | self.OBSOLETE) 139 140 self.mask_error = self.LOCAL_ERROR | self.NODE_ERROR | self.NETWORK_ERROR | self.UNKNOWN_ERROR