def _insert_record(self, sequenced_item): position = getattr(sequenced_item, self.field_names.position) if not isinstance(position, int): raise NotImplementedError( "Popo record manager only supports sequencing with integers, " "but position was a {}".format(type(position))) sequence_id = getattr(sequenced_item, self.field_names.sequence_id) try: application_records = self._all_sequence_records[ self.application_name] except KeyError: sequence_records = {} application_records = {sequence_id: sequence_records} self._all_sequence_records[ self.application_name] = application_records self._all_sequence_max[self.application_name] = {} else: try: sequence_records = application_records[sequence_id] except KeyError: sequence_records = {} application_records[sequence_id] = sequence_records if position in sequence_records: raise RecordConflictError(position, len(sequence_records)) if self.notification_id_name: # Just make sure we aren't making a gap in the sequence. if sequence_records: max_position = self._all_sequence_max[ self.application_name][sequence_id] next_position = max_position + 1 else: next_position = 0 if position != next_position: raise AssertionError( "Next position for sequence {} is {}, not {}".format( sequence_id, next_position, position)) sequence_records[position] = sequenced_item self._all_sequence_max[self.application_name][sequence_id] = position # Write a notification record. if self.notification_id_name: try: notification_records = self._all_notification_records[ self.application_name] except KeyError: notification_records = {} self._all_notification_records[ self.application_name] = notification_records next_notification_id = (self._get_max_record_id() or 0) + 1 notification_records[next_notification_id] = { 'notification_id': next_notification_id, 'sequenced_item': sequenced_item, } self._all_notification_max[ self.application_name] = next_notification_id
def write_records(self, records, tracking_kwargs=None): with self._rw_lock.gen_wlock(): # Write event and notification records. self._insert_records(records) if tracking_kwargs: # Write a tracking record. upstream_application_name = tracking_kwargs[ 'upstream_application_name'] application_name = tracking_kwargs['application_name'] notification_id = tracking_kwargs['notification_id'] assert application_name == self.application_name, ( application_name, self.application_name) try: app_tracking_records = self._all_tracking_records[ application_name] except KeyError: app_tracking_records = {} self._all_tracking_records[ self.application_name] = app_tracking_records try: upstream_tracking_records = app_tracking_records[ upstream_application_name] except KeyError: upstream_tracking_records = set() app_tracking_records[ upstream_application_name] = upstream_tracking_records if notification_id in upstream_tracking_records: raise RecordConflictError( (application_name, upstream_application_name, notification_id)) upstream_tracking_records.add(notification_id)
def write_records( self, records: Iterable[Any], tracking_kwargs: Optional[TrackingKwargs] = None, orm_objs_pending_save: Optional[Sequence[Any]] = None, orm_objs_pending_delete: Optional[Sequence[Any]] = None, ) -> None: with self._rw_lock.gen_wlock(): # Write event and notification records. if self.notification_id_name: records = list(records) all_notification_ids = set( getattr(r, self.notification_id_name) for r in records) if None in all_notification_ids: if len(all_notification_ids) > 1: raise ProgrammingError("Only some records have IDs") for record in records: self._insert_record(record) if tracking_kwargs: # Write a tracking record. upstream_application_name = tracking_kwargs[ "upstream_application_name"] application_name = tracking_kwargs["application_name"] notification_id = tracking_kwargs["notification_id"] assert application_name == self.application_name, ( application_name, self.application_name, ) try: app_tracking_records = self._all_tracking_records[ application_name] except KeyError: app_tracking_records = {} self._all_tracking_records[ self.application_name] = app_tracking_records try: upstream_tracking_records = app_tracking_records[ upstream_application_name] except KeyError: upstream_tracking_records = set() app_tracking_records[ upstream_application_name] = upstream_tracking_records if notification_id in upstream_tracking_records: raise RecordConflictError( (application_name, upstream_application_name, notification_id)) upstream_tracking_records.add(notification_id)
def write_records( self, records: Iterable[Any], tracking_kwargs: Optional[TrackingKwargs] = None, orm_objs_pending_save: Optional[Sequence[Any]] = None, orm_objs_pending_delete: Optional[Sequence[Any]] = None, ) -> None: with self._rw_lock.gen_wlock(): # Write event and notification records. for record in records: self._insert_record(record) if tracking_kwargs: # Write a tracking record. upstream_application_name = tracking_kwargs["upstream_application_name"] application_name = tracking_kwargs["application_name"] notification_id = tracking_kwargs["notification_id"] assert application_name == self.application_name, ( application_name, self.application_name, ) try: app_tracking_records = self._all_tracking_records[application_name] except KeyError: app_tracking_records = {} self._all_tracking_records[ self.application_name ] = app_tracking_records try: upstream_tracking_records = app_tracking_records[ upstream_application_name ] except KeyError: upstream_tracking_records = set() app_tracking_records[ upstream_application_name ] = upstream_tracking_records if notification_id in upstream_tracking_records: raise RecordConflictError( (application_name, upstream_application_name, notification_id) ) upstream_tracking_records.add(notification_id)
def _insert_record(self, record: NamedTuple) -> None: position = getattr(record, self.field_names.position) if not isinstance(position, int): raise NotImplementedError( "Popo record manager only supports sequencing with integers, " "but position was a {}".format(type(position))) if self.notification_id_name: notification_id = getattr(record, self.notification_id_name) if notification_id != EVENT_NOT_NOTIFIABLE: if notification_id is not None: if not isinstance(notification_id, int): raise ProgrammingError("%s must be an %s not %s: %s" % ( self.notification_id_name, int, type(notification_id), record.__dict__, )) sequence_id = getattr(record, self.field_names.sequence_id) try: application_records = self._all_sequence_records[ self.application_name] except KeyError: sequence_records: Dict[int, NamedTuple] = {} application_records = {sequence_id: sequence_records} self._all_sequence_records[ self.application_name] = application_records self._all_sequence_max[self.application_name] = {} else: try: sequence_records = application_records[sequence_id] except KeyError: sequence_records = {} application_records[sequence_id] = sequence_records if position in sequence_records: raise RecordConflictError(position, len(sequence_records)) if self.notification_id_name: # Just make sure we aren't making a gap in the sequence. if sequence_records: max_position = self._all_sequence_max[ self.application_name][sequence_id] next_position = max_position + 1 else: next_position = 0 if position != next_position: raise AssertionError( "Next position for sequence {} is {}, not {}".format( sequence_id, next_position, position)) sequence_records[position] = record self._all_sequence_max[self.application_name][sequence_id] = position # Write a notification record. if self.notification_id_name: try: notification_records = self._all_notification_records[ self.application_name] except KeyError: notification_records = {} self._all_notification_records[ self.application_name] = notification_records if self.notification_id_name: notification_id = getattr(record, self.notification_id_name) if notification_id == EVENT_NOT_NOTIFIABLE: setattr(record, self.notification_id_name, None) else: if notification_id is None: notification_id = (self._get_max_record_id() or 0) + 1 setattr(record, self.notification_id_name, notification_id) notification_records[notification_id] = { "notification_id": notification_id, "sequenced_item": record, } self._all_notification_max[ self.application_name] = notification_id
def raise_record_integrity_error(self, e): raise RecordConflictError(e)
def raise_sequenced_item_conflict(self): msg = "Position already taken in sequence" raise RecordConflictError(msg)
def raise_record_integrity_error(self, e: Exception) -> None: raise RecordConflictError(e)
def raise_sequenced_item_conflict(self, exp=None) -> None: msg = "Position already taken in sequence" raise RecordConflictError(exp or msg)