예제 #1
0
    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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #5
0
    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
예제 #6
0
 def raise_record_integrity_error(self, e):
     raise RecordConflictError(e)
예제 #7
0
 def raise_sequenced_item_conflict(self):
     msg = "Position already taken in sequence"
     raise RecordConflictError(msg)
예제 #8
0
 def raise_record_integrity_error(self, e: Exception) -> None:
     raise RecordConflictError(e)
예제 #9
0
 def raise_sequenced_item_conflict(self, exp=None) -> None:
     msg = "Position already taken in sequence"
     raise RecordConflictError(exp or msg)