|
1 | | -import copy |
2 | 1 | import uuid |
3 | 2 |
|
4 | | -from sqlalchemy.orm import Session |
5 | | - |
6 | | -from config.container import Container |
| 3 | +from config.container import TopLevelContainer |
| 4 | +from modules.catalog.application.command import CreateListingDraftCommand |
| 5 | +from modules.catalog.application.query import GetAllListings |
| 6 | +from modules.catalog.domain.repositories import ListingRepository |
7 | 7 | from modules.catalog.infrastructure.listing_repository import Base |
| 8 | +from seedwork.domain.value_objects import Money |
8 | 9 | from seedwork.infrastructure.logging import LoggerFactory, logger |
9 | | -from seedwork.infrastructure.request_context import request_context |
10 | 10 |
|
11 | 11 | # a sample command line script to print all listings |
12 | 12 | # run with "cd src && python -m cli" |
13 | 13 |
|
14 | 14 | # configure logger prior to first usage |
15 | 15 | LoggerFactory.configure(logger_name="cli") |
16 | 16 |
|
17 | | -container = Container() |
| 17 | +container = TopLevelContainer() |
18 | 18 | container.config.from_dict( |
19 | 19 | dict( |
20 | 20 | # DATABASE_URL="sqlite+pysqlite:///:memory:", |
|
24 | 24 | ) |
25 | 25 | ) |
26 | 26 |
|
27 | | -engine = container.db().engine() |
| 27 | +# let's create the database schema |
| 28 | +engine = container.db_engine() |
28 | 29 | Base.metadata.create_all(engine) |
29 | 30 |
|
| 31 | +# let's create a new application instance |
| 32 | +app = container.application() |
| 33 | + |
| 34 | + |
| 35 | +# let's query the listings, this method implicitly creates a transaction context and then executes a query |
| 36 | +# see `get_all_listings` query handler in `src/modules/catalog/application/query/get_all_listings.py` |
| 37 | +query_result = app.execute_query(GetAllListings()) |
| 38 | + |
| 39 | +# now let's print the listings |
| 40 | +listings = query_result.payload |
| 41 | +print("Listings:") |
| 42 | +for listing in listings: |
| 43 | + print(f"{listing['id']} - {listing['title']}") |
| 44 | + |
| 45 | +# now we are explicitly creating a transaction context, this time we want to execute a command |
| 46 | +with app.transaction_context() as ctx: |
| 47 | + # see `create_listing_draft` command handler in `src/modules/catalog/application/command/create_listing_draft.py` |
| 48 | + ctx.execute_command( |
| 49 | + CreateListingDraftCommand( |
| 50 | + listing_id=uuid.uuid4(), |
| 51 | + title="First listing", |
| 52 | + description="...", |
| 53 | + ask_price=Money(100), |
| 54 | + seller_id=uuid.UUID(int=1), |
| 55 | + ) |
| 56 | + ) |
30 | 57 |
|
31 | | -from seedwork.spike.test_scratch import ( |
32 | | - ActivateUserCommand, |
33 | | - Application, |
34 | | - CommandResult, |
35 | | - DependencyProvider, |
36 | | - TransactionContext, |
37 | | -) |
38 | | - |
39 | | - |
40 | | -class CustomDependencyProvider(DependencyProvider): |
41 | | - def __init__(self, ioc_container): |
42 | | - self.ioc_container = ioc_container |
43 | | - |
44 | | - |
45 | | -provider = CustomDependencyProvider(container) |
46 | | -app = Application(provider) |
47 | | - |
48 | | - |
49 | | -@app.on_enter_transaction_context |
50 | | -def on_enter_transaction_context(context: TransactionContext): |
51 | | - db_session = Session(engine) |
52 | | - correlation_id = uuid.uuid4() |
53 | | - context.dependency_provider = copy.deepcopy(app.dependency_provider) |
54 | | - context.dependency_provider["correlation_id"] = correlation_id |
55 | | - context.dependency_provider["db_session"] = db_session |
56 | | - |
57 | | - |
58 | | -@app.on_exit_transaction_context |
59 | | -def on_exit_transaction_context(context: TransactionContext, exc_type, exc_val, exc_tb): |
60 | | - db_session = context.dependency_provider["db_session"] |
61 | | - if exc_val is None: |
62 | | - db_session.commit() |
63 | | - else: |
64 | | - db_session.rollback() |
65 | | - context.dependency_provider["db_session"].close() |
66 | | - |
67 | | - |
68 | | -@app.transaction_middleware |
69 | | -def logging_middleware(next: callable, context: TransactionContext, task): |
70 | | - correlation_id = context.dependency_provider["correlation_id"] |
71 | | - request_context.correlation_id.set(correlation_id) |
72 | | - logger.info(f"transaction started for {task}") |
73 | | - result = next() |
74 | | - logger.info(f"transaction finished with {result}") |
75 | | - return result |
76 | | - |
77 | | - |
78 | | -@app.transaction_middleware |
79 | | -def sql_alchemy_session_middleware(next: callable, context: TransactionContext, task): |
80 | | - db_session = context.dependency_provider["db_session"] |
81 | | - logger.debug(f"session {db_session} started") |
82 | | - try: |
83 | | - result = next() |
84 | | - db_session.commit() |
85 | | - logger.debug(f"session {db_session} committed") |
86 | | - return result |
87 | | - except: |
88 | | - db_session.rollback() |
89 | | - logger.debug(f"session {db_session} rolled back") |
90 | | - finally: |
91 | | - db_session.close() |
92 | | - |
93 | | - |
94 | | -@app.command_handler(ActivateUserCommand) |
95 | | -def activate_user( |
96 | | - command: ActivateUserCommand, user_repository, db_session |
97 | | -) -> CommandResult: |
98 | | - logger.info(f"activate_user {db_session} {user_repository}") |
99 | | - try: |
100 | | - user = user_repository.get_by_id(command.user_id) |
101 | | - except: |
102 | | - user = None |
103 | | - return CommandResult(user) |
104 | | - |
105 | | - |
106 | | -with app.transaction_context(correlation_id="foo") as ctx: |
107 | | - ctx.execute_command(ActivateUserCommand(user_id=uuid.UUID(int=1))) |
108 | | - ctx.execute_command(ActivateUserCommand(user_id=uuid.UUID(int=2))) |
| 58 | +# use transaction context to acccess any dependency (i.e a repository, a service, etc.) |
| 59 | +with app.transaction_context() as ctx: |
| 60 | + listing_repository = ctx.get_service(ListingRepository) |
| 61 | + listing_count = listing_repository.count() |
| 62 | + logger.info(f"There are {listing_count} listings in the database") |
0 commit comments