arxiv.submission.domain.event.base module¶
Provides the base event class.
-
class
arxiv.submission.domain.event.base.
Event
(creator, created=None, proxy=None, client=None, submission_id=None, committed=False, before=None, after=None, event_type=<factory>, event_version=<factory>)[source]¶ Bases:
object
Base class for submission-related events/commands.
An event represents a change to a
domain.submission.Submission
. Rather than changing submissions directly, an application should create (and store) events. Each event class must inherit from this base class, extend it with whatever data is needed for the event, and define methods for validation and projection (changing a submission):validate(self, submission: Submission) -> None
should raiseInvalidEvent
if the event instance has invalid data.project(self, submission: Submission) -> Submission
should perform changes to thedomain.submission.Submission
and return it.
An event class also provides a hook for doing things automatically when the submission changes. To register a function that gets called when an event is committed, use the
bind()
method.-
after
= None¶ The state of the submission after the event.
-
before
= None¶ The state of the submission prior to the event.
-
classmethod
bind
(condition=None)[source]¶ Generate a decorator to bind a callback to an event type.
To register a function that will be called whenever an event is committed, decorate it like so:
@MyEvent.bind() def say_hello(event: MyEvent, before: Submission, after: Submission, creator: Agent) -> Iterable[Event]: yield SomeOtherEvent(...)
The callback function will be passed the event that triggered it, the state of the submission before and after the triggering event was applied, and a
System
agent that can be used as the creator of subsequent events. It should return an iterable of otherEvent
instances, either by yielding them, or by returning an iterable object of some kind.By default, callbacks will only be called if the creator of the trigger event is not a
System
instance. This makes it less easy to define infinite chains of callbacks. You can pass a custom condition to the decorator, for example:def jill_created_an_event(event: MyEvent, before: Submission, after: Submission) -> bool: return event.creator.username == 'jill' @MyEvent.bind(jill_created_an_event) def say_hi(event: MyEvent, before: Submission, after: Submission, creator: Agent) -> Iterable[Event]: yield SomeOtherEvent(...)
Note that the condition signature is
(event: MyEvent, before: Submission, after: Submission) -> bool
.- Parameters
condition (Callable) – A callable with the signature
(event: Event, before: Submission, after: Submission) -> bool
. If this callable returnsTrue
, the callback will be triggered when the event to which it is bound is saved. The default condition is that the event was not created bySystem
- Return type
- Returns
Callable – Decorator for a callback function, with signature
(event: Event, before: Submission, after: Submission, creator: Agent = System(...)) -> Iterable[Event]
.
-
client
= None¶ The client through which the
creator
performed the operation.If the creator was directly involved in the operation, this property should be the client that facilitated the operation.
-
commit
(store)[source]¶ Persist this event instance using an injected store method.
- Parameters
save (Callable) – Should have signature
(*Event, submission_id: int) -> Tuple[Event, Submission]
.- Return type
Tuple
[Submission
,Iterable
[Event
]]- Returns
Submission
– State of the submission after storage. Some changes may have been made to ensure consistency with the underlying datastore.list – Items are
Event
instances.
-
committed
= False¶ Indicates whether the event has been committed to the database.
This should generally not be set from outside this package.
-
created
= None¶ The timestamp when the event was originally committed.
-
creator
= None¶ The agent responsible for the operation represented by this event.
This is not necessarily the creator of the submission.
-
proxy
= None¶ The agent who facilitated the operation on behalf of the
creator
.This may be an API client, or another user who has been designated as a proxy. Note that proxy implies that the creator was not directly involved.
-
submission_id
= None¶ The primary identifier of the submission being operated upon.
This is defined as optional to support creation events, and to facilitate chaining of events with creation events in the same transaction.