-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
change composer interface. update documentation
- Loading branch information
Showing
28 changed files
with
499 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Events and publish-subscribe | ||
============================ | ||
|
||
Application modules can interact by publishing and subscribing to messages. Events can be published | ||
using a ``TransactionContext``, and received by an event handler. There can be multiple handlers bound to | ||
a single event. If the application is receiving an event from an external source, | ||
it should be processed using ``Application.publish()``: | ||
|
||
|
||
.. testcode:: | ||
|
||
from lato import Application, ApplicationModule, Event, Command, TransactionContext | ||
|
||
class SampleCommand(Command): | ||
pass | ||
|
||
class FooHappened(Event): | ||
source: str | ||
|
||
foo_module = ApplicationModule(name="foo") | ||
@foo_module.handler(SampleCommand) | ||
def call_foo(command: SampleCommand, ctx: TransactionContext): | ||
print("handling foo") | ||
ctx.publish(FooHappened(source="foo")) | ||
|
||
bar_module = ApplicationModule(name="bar") | ||
@bar_module.handler(FooHappened) | ||
def on_foo_happened(event: FooHappened): | ||
print(f"handling event from {event.source}") | ||
|
||
foobar = Application() | ||
foobar.include_submodule(foo_module) | ||
foobar.include_submodule(bar_module) | ||
|
||
foobar.execute(SampleCommand()) | ||
foobar.publish(FooHappened(source="external source")) | ||
|
||
And the output is: | ||
|
||
.. testoutput:: | ||
|
||
handling foo | ||
handling event from foo | ||
handling event from external source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,74 @@ | ||
Transaction Middleware | ||
====================== | ||
Transaction callbacks and middlewares | ||
===================================== | ||
|
||
... | ||
In most cases, the handler is executed by calling one of the Application methods: :func:`~lato.Application.call`, | ||
:func:`~lato.Application.execute`, or :func:`~lato.Application.publish`, which creates the transaction context under the | ||
hood. | ||
|
||
When :func:`~lato.Application.call` or similar method is executed, the lifecycle of handler execution is as following: | ||
|
||
1. ``on_enter_transaction_context`` callback is invoked | ||
|
||
2. ``transaction_middleware`` functions, wrapping the handler are invoked | ||
|
||
3. handler function is invoked | ||
|
||
4. ``on_exit_transaction_context`` callback is invoked | ||
|
||
The application can be configured to use any of the callbacks by using decorators: | ||
|
||
.. testcode:: | ||
|
||
from typing import Optional, Callable | ||
from lato import Application, TransactionContext | ||
|
||
|
||
app = Application() | ||
|
||
@app.on_enter_transaction_context | ||
def on_enter_transaction_context(ctx: TransactionContext): | ||
print("starting transaction") | ||
|
||
@app.on_exit_transaction_context | ||
def on_exit_transaction_context(ctx: TransactionContext, | ||
exception: Optional[Exception]=None): | ||
print("exiting transaction context") | ||
|
||
@app.transaction_middleware | ||
def middleware1(ctx: TransactionContext, call_next: Callable): | ||
print("entering middleware1") | ||
result = call_next() # will call middleware2 | ||
print("exiting middleware1") | ||
return result | ||
|
||
@app.transaction_middleware | ||
def middleware2(ctx: TransactionContext, call_next: Callable): | ||
print("entering middleware2") | ||
result = call_next() # will call the handler | ||
print("exiting middleware2") | ||
return f"[{result}]" | ||
|
||
def to_uppercase(s): | ||
print("calling handler") | ||
return s.upper() | ||
|
||
|
||
print(app.call(to_uppercase, "foo")) | ||
|
||
This will generate the output: | ||
|
||
.. testoutput:: | ||
|
||
starting transaction | ||
entering middleware1 | ||
entering middleware2 | ||
calling handler | ||
exiting middleware2 | ||
exiting middleware1 | ||
exiting transaction context | ||
[FOO] | ||
|
||
Any of the callbacks is optional, and there can be multiple ``transaction_middleware`` callbacks. | ||
``on_enter_transaction_context`` is a good place to set up the transaction level dependencies, i.e. the dependencies | ||
that change with every transaction - correlation id, current time, database session, etc. ``call_next`` is a ``functools.partial`` object, | ||
so you can inspect is arguments using ``call_next.args`` and ``call_next.keywords``. |
Oops, something went wrong.