qena-shared-lib 0.1.18__py3-none-any.whl → 0.1.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qena_shared_lib/__init__.py +18 -1
- qena_shared_lib/alias.py +27 -0
- qena_shared_lib/cache.py +61 -0
- qena_shared_lib/enums.py +8 -0
- qena_shared_lib/eventbus.py +373 -0
- qena_shared_lib/exceptions.py +2 -5
- qena_shared_lib/http/__init__.py +23 -0
- qena_shared_lib/http/_request.py +24 -0
- qena_shared_lib/http/_response.py +24 -0
- qena_shared_lib/mongodb.py +599 -0
- qena_shared_lib/rabbitmq/__init__.py +2 -0
- qena_shared_lib/rabbitmq/_listener.py +8 -32
- qena_shared_lib/rabbitmq/message/__init__.py +22 -0
- qena_shared_lib/rabbitmq/message/_inbound.py +13 -0
- qena_shared_lib/rabbitmq/message/_outbound.py +13 -0
- qena_shared_lib/redis.py +47 -0
- qena_shared_lib/remotelogging/_base.py +14 -8
- qena_shared_lib/remotelogging/logstash/_base.py +1 -0
- qena_shared_lib/sync.py +91 -0
- {qena_shared_lib-0.1.18.dist-info → qena_shared_lib-0.1.20.dist-info}/METADATA +394 -34
- {qena_shared_lib-0.1.18.dist-info → qena_shared_lib-0.1.20.dist-info}/RECORD +28 -16
- qena_shared_lib-0.1.20.dist-info/WHEEL +4 -0
- qena_shared_lib-0.1.18.dist-info/WHEEL +0 -4
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: qena-shared-lib
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.20
|
|
4
4
|
Summary: A shared tools for other services
|
|
5
|
-
Requires-Python: >=3.10
|
|
6
5
|
Requires-Dist: fastapi[all]==0.115.6
|
|
7
6
|
Requires-Dist: prometheus-client==0.21.1
|
|
8
7
|
Requires-Dist: prometheus-fastapi-instrumentator==7.0.2
|
|
@@ -11,21 +10,28 @@ Requires-Dist: pydantic-core==2.27.1
|
|
|
11
10
|
Requires-Dist: pydantic==2.10.3
|
|
12
11
|
Requires-Dist: starlette==0.41.3
|
|
13
12
|
Requires-Dist: typing-extensions==4.12.2
|
|
13
|
+
Requires-Dist: aiokafka==0.12.0 ; extra == 'all'
|
|
14
|
+
Requires-Dist: cronsim==2.6 ; extra == 'all'
|
|
15
|
+
Requires-Dist: jwt==1.3.1 ; extra == 'all'
|
|
16
|
+
Requires-Dist: passlib[bcrypt]==1.7.4 ; extra == 'all'
|
|
17
|
+
Requires-Dist: pika==1.3.2 ; extra == 'all'
|
|
18
|
+
Requires-Dist: pymongo==4.15.3 ; extra == 'all'
|
|
19
|
+
Requires-Dist: redis==7.1.0 ; extra == 'all'
|
|
20
|
+
Requires-Dist: aiokafka==0.12.0 ; extra == 'kafka'
|
|
21
|
+
Requires-Dist: pymongo==4.15.3 ; extra == 'mongodb'
|
|
22
|
+
Requires-Dist: pika==1.3.2 ; extra == 'rabbitmq'
|
|
23
|
+
Requires-Dist: redis==7.1.0 ; extra == 'redis'
|
|
24
|
+
Requires-Dist: cronsim==2.6 ; extra == 'scheduler'
|
|
25
|
+
Requires-Dist: jwt==1.3.1 ; extra == 'security'
|
|
26
|
+
Requires-Dist: passlib[bcrypt]==1.7.4 ; extra == 'security'
|
|
27
|
+
Requires-Python: >=3.10
|
|
14
28
|
Provides-Extra: all
|
|
15
|
-
Requires-Dist: aiokafka==0.12.0; extra == 'all'
|
|
16
|
-
Requires-Dist: cronsim==2.6; extra == 'all'
|
|
17
|
-
Requires-Dist: jwt==1.3.1; extra == 'all'
|
|
18
|
-
Requires-Dist: passlib[bcrypt]==1.7.4; extra == 'all'
|
|
19
|
-
Requires-Dist: pika==1.3.2; extra == 'all'
|
|
20
29
|
Provides-Extra: kafka
|
|
21
|
-
|
|
30
|
+
Provides-Extra: mongodb
|
|
22
31
|
Provides-Extra: rabbitmq
|
|
23
|
-
|
|
32
|
+
Provides-Extra: redis
|
|
24
33
|
Provides-Extra: scheduler
|
|
25
|
-
Requires-Dist: cronsim==2.6; extra == 'scheduler'
|
|
26
34
|
Provides-Extra: security
|
|
27
|
-
Requires-Dist: jwt==1.3.1; extra == 'security'
|
|
28
|
-
Requires-Dist: passlib[bcrypt]==1.7.4; extra == 'security'
|
|
29
35
|
Description-Content-Type: text/markdown
|
|
30
36
|
|
|
31
37
|
# Qena shared lib
|
|
@@ -34,23 +40,66 @@ A shared tools for other services. It includes.
|
|
|
34
40
|
|
|
35
41
|
- FastAPI app builder
|
|
36
42
|
- A wrapper around fastapi to make it class based.
|
|
37
|
-
- RabbitMQ utility class to listen, respond, publish and make rpc request.
|
|
43
|
+
- RabbitMQ utility class to listen , respond , publish and make rpc request.
|
|
38
44
|
- Remote logging
|
|
39
45
|
- Logstash utility class to log message in `ecs` ( elastic common schema ).
|
|
40
|
-
- A simple task scheduler, to schedule task to run in specific time.
|
|
46
|
+
- A simple task scheduler , to schedule task to run in specific time.
|
|
41
47
|
- Background task runner.
|
|
42
|
-
- Security tools ( password hasher, jwt, acl ).
|
|
43
|
-
- IOC container to manager dependencies used across fastapi, rabbitmq manager and schedule manager.
|
|
48
|
+
- Security tools ( password hasher , jwt , acl ).
|
|
49
|
+
- IOC container to manager dependencies used across fastapi , rabbitmq manager and schedule manager.
|
|
50
|
+
- Kafka producer and consumer wrapper.
|
|
51
|
+
- Mongodb client wrapper , with repository and index manager.
|
|
52
|
+
- Redis wrapper with cache and distributed lock manager.
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
44
55
|
|
|
45
|
-
|
|
56
|
+
It is prefered to use [astral.sh / uv](https://docs.astral.sh/uv) as a package manager.
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
``` sh
|
|
59
|
+
$ uv add qena-shared-lib[all]
|
|
60
|
+
```
|
|
61
|
+
to install all extras , or specific extras `kafka` , `rabbitmq` , `scheduler` , `security` , `redis` or `mongodb`.
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
- [Environment variables](#environment-variables)
|
|
66
|
+
- [Http](#http)
|
|
67
|
+
- [Lifespan](#lifespan)
|
|
68
|
+
- [Dependencies](#dependencies)
|
|
69
|
+
- [Controllers](#controllers)
|
|
70
|
+
- [Routers](#routers)
|
|
71
|
+
- [Remote logging](#remote-logging)
|
|
72
|
+
- [Logstash](#logstash)
|
|
73
|
+
- [Rabbitmq](#rabbitmq)
|
|
74
|
+
- [Publisher](#publisher)
|
|
75
|
+
- [RPC client](#rpc-client)
|
|
76
|
+
- [Flow control](#flow-control)
|
|
77
|
+
- [Rpc reply](#rpc-reply)
|
|
78
|
+
- [Retry consumer](#retry-consumer)
|
|
79
|
+
- [Scheduler](#scheduler)
|
|
80
|
+
- [Background](#background)
|
|
81
|
+
- [Security](#security)
|
|
82
|
+
- [Password hasher](#password-hasher)
|
|
83
|
+
- [JWT](#jwt)
|
|
84
|
+
- [ACL](#acl)
|
|
85
|
+
- [Kafka](#kafka)
|
|
86
|
+
- [Producer](#producer)
|
|
87
|
+
- [Consumer](#consumer)
|
|
88
|
+
- [Mongodb](#mongodb)
|
|
89
|
+
- [Aggregation](#aggregation)
|
|
90
|
+
- [Index](#index)
|
|
91
|
+
- [Crud](#crud)
|
|
92
|
+
- [Redis](#redis)
|
|
93
|
+
- [Cache](#cache)
|
|
94
|
+
- [Distribute lock](#distribute-lock)
|
|
95
|
+
|
|
96
|
+
### Environment variables
|
|
48
97
|
|
|
49
98
|
- `QENA_SHARED_LIB_LOGGING_LOGGER_NAME` root logger name.
|
|
50
99
|
- `QENA_SHARED_LIB_SECURITY_UNAUTHORIZED_RESPONSE_CODE` an integer response on an authorized access of resource.
|
|
51
100
|
- `QENA_SHARED_LIB_SECURITY_TOKEN_HEADER` to header key for jwt token.
|
|
52
101
|
|
|
53
|
-
|
|
102
|
+
### Http
|
|
54
103
|
|
|
55
104
|
To create fastapi app.
|
|
56
105
|
|
|
@@ -190,9 +239,10 @@ def main() -> FastAPI:
|
|
|
190
239
|
...
|
|
191
240
|
```
|
|
192
241
|
|
|
193
|
-
|
|
242
|
+
### Remote logging
|
|
243
|
+
|
|
244
|
+
#### Logstash
|
|
194
245
|
|
|
195
|
-
### Logstash
|
|
196
246
|
``` py
|
|
197
247
|
from qena_shared_lib.remotelogging import BaseRemoteLogSender
|
|
198
248
|
from qena_shared_lib.remotelogging.logstash import HTTPSender, # TCPSender
|
|
@@ -243,7 +293,7 @@ def log_message(
|
|
|
243
293
|
remote_logger.info(message)
|
|
244
294
|
```
|
|
245
295
|
|
|
246
|
-
|
|
296
|
+
### Rabbitmq
|
|
247
297
|
|
|
248
298
|
To create rabbitmq connection manager.
|
|
249
299
|
|
|
@@ -291,7 +341,7 @@ def main() -> FastAPI:
|
|
|
291
341
|
...
|
|
292
342
|
```
|
|
293
343
|
|
|
294
|
-
|
|
344
|
+
#### Publisher
|
|
295
345
|
|
|
296
346
|
``` py
|
|
297
347
|
@router.post("")
|
|
@@ -308,7 +358,7 @@ async def store_user(
|
|
|
308
358
|
# await publisher.publish_as_arguments(user)
|
|
309
359
|
```
|
|
310
360
|
|
|
311
|
-
|
|
361
|
+
#### RPC client
|
|
312
362
|
|
|
313
363
|
``` py
|
|
314
364
|
@router.get("")
|
|
@@ -327,7 +377,7 @@ async def get_user(
|
|
|
327
377
|
return user
|
|
328
378
|
```
|
|
329
379
|
|
|
330
|
-
|
|
380
|
+
#### Flow control
|
|
331
381
|
|
|
332
382
|
``` py
|
|
333
383
|
from qena_shared_lib.rabbitmq import ... , ListenerContext
|
|
@@ -346,7 +396,7 @@ class UserConsumer(ListenerBase):
|
|
|
346
396
|
|
|
347
397
|
```
|
|
348
398
|
|
|
349
|
-
|
|
399
|
+
#### Rpc reply
|
|
350
400
|
|
|
351
401
|
Optionally it is possible to reply to rpc calls, through.
|
|
352
402
|
|
|
@@ -366,7 +416,7 @@ class UserWorker(ListenerBase):
|
|
|
366
416
|
...
|
|
367
417
|
```
|
|
368
418
|
|
|
369
|
-
|
|
419
|
+
#### Retry consumer
|
|
370
420
|
|
|
371
421
|
Consumer can retry to consumer a message in an event of failure.
|
|
372
422
|
|
|
@@ -440,7 +490,7 @@ def main() -> FastAPI:
|
|
|
440
490
|
|
|
441
491
|
|
|
442
492
|
|
|
443
|
-
|
|
493
|
+
### Scheduler
|
|
444
494
|
|
|
445
495
|
``` py
|
|
446
496
|
from qena_shared_lib.scheduler import (
|
|
@@ -501,7 +551,7 @@ def main() -> FastAPI:
|
|
|
501
551
|
...
|
|
502
552
|
```
|
|
503
553
|
|
|
504
|
-
|
|
554
|
+
### Background
|
|
505
555
|
|
|
506
556
|
``` py
|
|
507
557
|
from qena_shared_lib.background import Background
|
|
@@ -545,9 +595,9 @@ async def process_data(
|
|
|
545
595
|
background.add_task(BackgroundTask(data_processor, data))
|
|
546
596
|
```
|
|
547
597
|
|
|
548
|
-
|
|
598
|
+
### Security
|
|
549
599
|
|
|
550
|
-
|
|
600
|
+
#### Password hasher
|
|
551
601
|
|
|
552
602
|
``` py
|
|
553
603
|
from qena_shared_lib.security import PasswordHasher
|
|
@@ -579,7 +629,7 @@ def main() -> FastAPI:
|
|
|
579
629
|
...
|
|
580
630
|
```
|
|
581
631
|
|
|
582
|
-
|
|
632
|
+
#### JWT
|
|
583
633
|
|
|
584
634
|
``` py
|
|
585
635
|
from qena_shared_lib.security import JwtAdapter
|
|
@@ -621,7 +671,7 @@ def main() -> FastAPI:
|
|
|
621
671
|
...
|
|
622
672
|
```
|
|
623
673
|
|
|
624
|
-
|
|
674
|
+
#### ACL
|
|
625
675
|
|
|
626
676
|
``` py
|
|
627
677
|
from qena_shared_lib.security import Authorization
|
|
@@ -655,3 +705,313 @@ async def get_users(
|
|
|
655
705
|
)
|
|
656
706
|
...
|
|
657
707
|
```
|
|
708
|
+
|
|
709
|
+
### Kafka
|
|
710
|
+
|
|
711
|
+
``` py
|
|
712
|
+
from qena_shared_lib.kafka import KafkaManager
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
@asynccontextmanager
|
|
716
|
+
async def lifespan(app: FastAPI):
|
|
717
|
+
kafka = get_service(KafkaManager)
|
|
718
|
+
|
|
719
|
+
await kafka.connect()
|
|
720
|
+
|
|
721
|
+
yield
|
|
722
|
+
|
|
723
|
+
await kafka.disconnect()
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def main() -> FastAPI:
|
|
727
|
+
...
|
|
728
|
+
|
|
729
|
+
kafka = KafkaManager(
|
|
730
|
+
remote_logger=...,
|
|
731
|
+
bootstrap_servers="127.0.0.1:9092",
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
builder.with_singleton(
|
|
735
|
+
service=KafkaManager,
|
|
736
|
+
instance=kafka,
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
...
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
#### Producer
|
|
743
|
+
|
|
744
|
+
``` py
|
|
745
|
+
class UserService:
|
|
746
|
+
def __init__(self, kafka: KafkaManager):
|
|
747
|
+
self._kafka = kafka
|
|
748
|
+
|
|
749
|
+
async def create_user(self):
|
|
750
|
+
...
|
|
751
|
+
|
|
752
|
+
async with await self._kafka.producer("user") as producer:
|
|
753
|
+
await producer.send(key="some_key", value=user)
|
|
754
|
+
|
|
755
|
+
...
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
#### Consumer
|
|
759
|
+
|
|
760
|
+
``` py
|
|
761
|
+
from qena_shared_lib.kafka import (
|
|
762
|
+
ConsumerBase,
|
|
763
|
+
consume,
|
|
764
|
+
consumer,
|
|
765
|
+
)
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
@consumer(["user"])
|
|
769
|
+
class USerConsumer(ConsumerBase):
|
|
770
|
+
def __init__(self, user_service: UserService):
|
|
771
|
+
self._user_service = user_service
|
|
772
|
+
|
|
773
|
+
@consume()
|
|
774
|
+
async def user_created(self, key: Any | None, value: Any | None):
|
|
775
|
+
...
|
|
776
|
+
|
|
777
|
+
await self._user_service.create_user(...)
|
|
778
|
+
|
|
779
|
+
...
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Mongodb
|
|
783
|
+
|
|
784
|
+
``` py
|
|
785
|
+
from qena_shared_lib.mongodb import MongoDBManager
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
@asynccontextmanager
|
|
789
|
+
async def lifespan(app: FastAPI):
|
|
790
|
+
db = get_service(MongoDBManager)
|
|
791
|
+
|
|
792
|
+
await db.connect()
|
|
793
|
+
|
|
794
|
+
yield
|
|
795
|
+
|
|
796
|
+
await db.disconnect()
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def main() -> FastAPI:
|
|
800
|
+
...
|
|
801
|
+
|
|
802
|
+
db = MongoDBManager(
|
|
803
|
+
connection_string="mongodb://127.0.0.1:27017",
|
|
804
|
+
db="userDb"
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
builder.with_singleton(
|
|
808
|
+
service=MongoDBManager,
|
|
809
|
+
instance=db
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
...
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
#### Crud
|
|
816
|
+
|
|
817
|
+
``` py
|
|
818
|
+
from qena_shared_lib.mongodb import (
|
|
819
|
+
Document,
|
|
820
|
+
MongoDBManager,
|
|
821
|
+
ProjectedDocument,
|
|
822
|
+
RepositoryBase,
|
|
823
|
+
)
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
class User(Document):
|
|
827
|
+
__collection_name__ = "users"
|
|
828
|
+
|
|
829
|
+
full_name: str
|
|
830
|
+
phone: str
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class FullNameProjectedUser(ProjectedDocument):
|
|
834
|
+
full_name: str
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
class UserRepository(RepositoryBase[User]):
|
|
838
|
+
pass
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
class UserService:
|
|
842
|
+
def __init__(self, user_repository: UserRepository):
|
|
843
|
+
self._user_repository = user_repository
|
|
844
|
+
|
|
845
|
+
async def add_user(self):
|
|
846
|
+
await self._user_repository.insert(
|
|
847
|
+
User(
|
|
848
|
+
full_name="user one",
|
|
849
|
+
phone="+251900000000"
|
|
850
|
+
)
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
async def get_user(self):
|
|
854
|
+
user = await self._user_repository.find_by_filter(
|
|
855
|
+
filter={"phone": "+251900000000"}
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
async def get_user_fullname(self):
|
|
859
|
+
user = await self._user_repository.find_by_filter(
|
|
860
|
+
filter={"phone": "+251900000000"}, projection=FullNameProjectedUser
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
async def update_user(self):
|
|
864
|
+
user = await self._user_repository.find_by_filter(
|
|
865
|
+
filter={"phone": "+251900000000"}, projection
|
|
866
|
+
)
|
|
867
|
+
user.phone = "+251900000001"
|
|
868
|
+
|
|
869
|
+
await user_repository.replace(user)
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
#### Aggregation
|
|
873
|
+
|
|
874
|
+
``` py
|
|
875
|
+
class AggregatedUser(AggregatedDocument):
|
|
876
|
+
__pipeline__ = [
|
|
877
|
+
{"$match": {"phone": {"$in": ["+251900000000", "+251900000001"]}}},
|
|
878
|
+
{"$project": {"fullName": True}},
|
|
879
|
+
]
|
|
880
|
+
|
|
881
|
+
full_name: str
|
|
882
|
+
|
|
883
|
+
class UserService:
|
|
884
|
+
...
|
|
885
|
+
|
|
886
|
+
async def get_user_fullnames(self):
|
|
887
|
+
users = user_repository.aggregate(aggregation=AggregatedUser)
|
|
888
|
+
|
|
889
|
+
...
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
#### Index
|
|
893
|
+
|
|
894
|
+
``` py
|
|
895
|
+
from qena_shared_lib.mongodb import Document, IndexManager, IndexModel
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
class User(Document):
|
|
899
|
+
__collection_name__ = "users"
|
|
900
|
+
__indexes__ = [IndexModel("phone")]
|
|
901
|
+
|
|
902
|
+
full_name: str
|
|
903
|
+
phone: str
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
async def manage_indexes():
|
|
907
|
+
...
|
|
908
|
+
|
|
909
|
+
index_manager = IndexManager(db=db, documents=[User])
|
|
910
|
+
|
|
911
|
+
await index_manager.create_indexes
|
|
912
|
+
|
|
913
|
+
...
|
|
914
|
+
|
|
915
|
+
await index_manager.drop_indexes()
|
|
916
|
+
|
|
917
|
+
...
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
### Redis
|
|
921
|
+
|
|
922
|
+
``` py
|
|
923
|
+
from qena_shared_lib.redis import RedisManager
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
@asynccontextmanager
|
|
927
|
+
async def lifespan(app: FastAPI):
|
|
928
|
+
redis_manager = get_service(RedisManager)
|
|
929
|
+
|
|
930
|
+
await dredis_managerb.connect()
|
|
931
|
+
|
|
932
|
+
yield
|
|
933
|
+
|
|
934
|
+
await redis_manager.disconnect()
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
def main() -> FastAPI:
|
|
938
|
+
...
|
|
939
|
+
|
|
940
|
+
redis_manager = RedisManager("redis://127.0.0.1:6379")
|
|
941
|
+
|
|
942
|
+
builder.with_singleton(
|
|
943
|
+
service=RedisManager,
|
|
944
|
+
instance=redis_manager
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
...
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
#### Cache
|
|
951
|
+
|
|
952
|
+
``` py
|
|
953
|
+
from qena_shared_lib.cache import CachedObject, CacheManager
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
def main() -> FastAPI:
|
|
957
|
+
...
|
|
958
|
+
|
|
959
|
+
cache_manager = CacheManager()
|
|
960
|
+
|
|
961
|
+
redis_manager.add(cache_manager)
|
|
962
|
+
builder.with_singleton(
|
|
963
|
+
service=CacheManager,
|
|
964
|
+
instance=cache_manager
|
|
965
|
+
)
|
|
966
|
+
|
|
967
|
+
...
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
class UserCache(CachedObject):
|
|
971
|
+
full_name: str
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
class UserService:
|
|
975
|
+
def __init__(self, cache_manager: CacheManager):
|
|
976
|
+
self._cache_manager = cache_manager
|
|
977
|
+
|
|
978
|
+
async def cache_user(self):
|
|
979
|
+
await self._cache_manager.set(
|
|
980
|
+
UserCache(full_name="user one")
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
async def get_cached_user(self):
|
|
984
|
+
user_cache = await self._cache_manager.get(UserCache)
|
|
985
|
+
|
|
986
|
+
async def unset_cached_user(self):
|
|
987
|
+
await self._cache_manager.unset(UserCache)
|
|
988
|
+
```
|
|
989
|
+
|
|
990
|
+
#### Distribute lock
|
|
991
|
+
|
|
992
|
+
``` py
|
|
993
|
+
from qena_shared_lib.sync import DistributedLockManager
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
def main() -> FastAPI:
|
|
997
|
+
...
|
|
998
|
+
|
|
999
|
+
distributed_lock_manager = DistributedLockManager()
|
|
1000
|
+
|
|
1001
|
+
redis_manager.add(distributed_lock_manager)
|
|
1002
|
+
builder.with_singleton(
|
|
1003
|
+
service=DistributedLockManager,
|
|
1004
|
+
instance=distributed_lock_manager
|
|
1005
|
+
)
|
|
1006
|
+
|
|
1007
|
+
...
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
class UserService:
|
|
1011
|
+
def __init__(self, distributed_lock_manager: DistributedLockManager):
|
|
1012
|
+
self._distributed_lock_manager = distributed_lock_manager
|
|
1013
|
+
|
|
1014
|
+
async def create_user(self):
|
|
1015
|
+
async with self._distributed_lock_manager("user_one_create") as _:
|
|
1016
|
+
...
|
|
1017
|
+
```
|
|
@@ -1,38 +1,50 @@
|
|
|
1
|
-
qena_shared_lib/__init__.py,sha256=
|
|
1
|
+
qena_shared_lib/__init__.py,sha256=cAuC24s_ef_CZNAqZpC2SnkfvLcZsUehrfAdQo15t8E,651
|
|
2
|
+
qena_shared_lib/alias.py,sha256=y0qXPNR6CHWYHaci9JgMbnV5x18PHkaTZy03vnpUpXQ,645
|
|
2
3
|
qena_shared_lib/application.py,sha256=0pvuy5PxH5fw5FptTI4ksUxNAh-hzr_d5beAMDiBzi8,7117
|
|
3
4
|
qena_shared_lib/background.py,sha256=SCZhZOwWgv5T0X4tMB_aTecKlMdT12bzqpbA4qoZQPA,3473
|
|
4
|
-
qena_shared_lib/
|
|
5
|
-
qena_shared_lib/exceptions.py,sha256=vKqZjU5XmVNE-zjQ5kZ9HlOELbAD8E6TPP1Kv6tPVKE,14593
|
|
6
|
-
qena_shared_lib/logging.py,sha256=HZiqbXpmJsAI7hheAaQ9EA8uj9yU0pMVCg64d_V0wzA,1748
|
|
7
|
-
qena_shared_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
qena_shared_lib/scheduler.py,sha256=Spp5PnpFJ0U4aLeFCNmje9zUA4zwkL-b7X8SSGkGssM,13579
|
|
9
|
-
qena_shared_lib/security.py,sha256=RAXBkfhytJl-2SOXYQTJMnUb789-8DNZKRjRtpod16Y,6372
|
|
10
|
-
qena_shared_lib/utils.py,sha256=crD8NJD1Se7ZHPCaQBCi3c7Y46lMvk8OsN_bZTbcyto,1184
|
|
5
|
+
qena_shared_lib/cache.py,sha256=tgOqy6fi_fN0EEhclPdlWWVAM2F0rd0eAU7ZyJm4CQQ,1676
|
|
11
6
|
qena_shared_lib/dependencies/__init__.py,sha256=W12RgJbhqZ9GiSV1nLlHmpwPzvQv8t7f4JEoazM_WYg,350
|
|
12
7
|
qena_shared_lib/dependencies/http.py,sha256=IBsMnRr8Jh8ixf2IcU6n1aYRMazI3fF9GLZxHM2dsXk,1492
|
|
13
8
|
qena_shared_lib/dependencies/miscellaneous.py,sha256=iGwAjatXb_JVSF13n1vdTRAgSKv19VtHo9ZbjjbkIco,753
|
|
14
|
-
qena_shared_lib/
|
|
9
|
+
qena_shared_lib/enums.py,sha256=qYOZUD8Or0O1uGoNRShMp-SzmkXDQ31djMVTG_yGxL4,107
|
|
10
|
+
qena_shared_lib/eventbus.py,sha256=Qk4TiJHGlnUNQkLTIWEuHe3MPyRmwUmkjbk5Y4dNSxE,11501
|
|
11
|
+
qena_shared_lib/exception_handling.py,sha256=oiPVaxD74y-dbB8hJsncPNd-Fphot60Q60tZQTbCZ50,13392
|
|
12
|
+
qena_shared_lib/exceptions.py,sha256=pByxZnxesxLVyHF2ARd0C0ioWLYZZVOtxPytJnF5EDo,14567
|
|
13
|
+
qena_shared_lib/http/__init__.py,sha256=F6CqzPsRx55fa5ozRkk2lSNJu28KPw9uI8zQwoo4lVU,2055
|
|
15
14
|
qena_shared_lib/http/_base.py,sha256=5jPAjiDmJIxjtMdhxNHpcTM_xbXC5eBMvy3U0tpB25Q,25199
|
|
16
15
|
qena_shared_lib/http/_exception_handlers.py,sha256=fkxW7KqyCy923f4f6s1qmd8gO-Oaoi-mLR9gaIWC-PU,6265
|
|
16
|
+
qena_shared_lib/http/_request.py,sha256=kppCnS5zZfvKl-hNO6ysqkVdtoXshFp6Ue_0O5apqXQ,426
|
|
17
|
+
qena_shared_lib/http/_response.py,sha256=sUd2ggu6IeKtNhoYAr-xZmEn40HLq5vLHpRcV7mZFnk,432
|
|
17
18
|
qena_shared_lib/kafka/__init__.py,sha256=59aii_0Is8cwEVQlK4w9Jk3YrOqojTa6ReJO0SBedog,392
|
|
18
19
|
qena_shared_lib/kafka/_base.py,sha256=H27YrSgA8iifSDkptFRSTcR4P-hoMqOLqPXpw9WpgvA,8251
|
|
19
20
|
qena_shared_lib/kafka/_consumer.py,sha256=aEOtAqMhFPIMYbKK_BMDwR2rd_eaDzBJ6xR3Ud5LhPE,19294
|
|
20
21
|
qena_shared_lib/kafka/_exception_handlers.py,sha256=D7Xh5eSpSkumQKvPfBmVB_E6vQxD58y41bFpP5Jzhqk,4084
|
|
21
22
|
qena_shared_lib/kafka/_producer.py,sha256=QtYfKzNtxeIT1EtGpS-tvFC342oPoleF1AOl20LfNXs,3941
|
|
22
|
-
qena_shared_lib/
|
|
23
|
+
qena_shared_lib/logging.py,sha256=HZiqbXpmJsAI7hheAaQ9EA8uj9yU0pMVCg64d_V0wzA,1748
|
|
24
|
+
qena_shared_lib/mongodb.py,sha256=CHkegKThenGB4A9bb0wNMLYGdrGo8-jDMx_3wRngIJ4,17056
|
|
25
|
+
qena_shared_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
qena_shared_lib/rabbitmq/__init__.py,sha256=g15fP9XQ1CHFBXZmeAxQcsppQ0Nx62gJ4VOK8nzW7T4,1254
|
|
23
27
|
qena_shared_lib/rabbitmq/_base.py,sha256=pKJL0PNrhUOXw4XUJ1iZsuCPVY3ykvO8ebIfeX9HwXo,21502
|
|
24
28
|
qena_shared_lib/rabbitmq/_channel.py,sha256=l67iMB2NqprQeypHBIS_jLeiQEqYxunh76-wq8zEHLw,5898
|
|
25
29
|
qena_shared_lib/rabbitmq/_exception_handlers.py,sha256=jL4McHxetlNOTpmnLggg3akwsVkXy8dGQLHHPPEDeiM,3718
|
|
26
|
-
qena_shared_lib/rabbitmq/_listener.py,sha256=
|
|
30
|
+
qena_shared_lib/rabbitmq/_listener.py,sha256=BwZ3YVTGI2sIMJWMoL7SnYN_RGfjBr1tYxaGqPkyrhc,51119
|
|
27
31
|
qena_shared_lib/rabbitmq/_pool.py,sha256=eEJswSoWoWzjh290doFYccn1cwQW6DgbdpHeU-7nZSg,2006
|
|
28
32
|
qena_shared_lib/rabbitmq/_publisher.py,sha256=57WruxVlZemA7XVDNHSNB3_2gI-ycIKDobepLGa_QoM,2511
|
|
29
33
|
qena_shared_lib/rabbitmq/_rpc_client.py,sha256=DKYvyPnmaMfa8Ymw1nLKinuFeG_H0Lc1OL8EUjN8M6U,9353
|
|
34
|
+
qena_shared_lib/rabbitmq/message/__init__.py,sha256=J0wKjSuwOC7urUffWdxGZ7x_F9S5S6EryC9NxuysOhY,439
|
|
35
|
+
qena_shared_lib/rabbitmq/message/_inbound.py,sha256=v744Vr4JZn9iE4GnD8uoQQLiD9TuKGZgLIiMwIcLGp4,272
|
|
36
|
+
qena_shared_lib/rabbitmq/message/_outbound.py,sha256=axf7OF2rA05ixdjM3PiHG33I3dJU2gS8GP-ooefX4Jk,274
|
|
37
|
+
qena_shared_lib/redis.py,sha256=N15rYGX5iMbFvFzCnSTtOBD_EIrdZ9xkoS1Sw9s-3tI,1262
|
|
30
38
|
qena_shared_lib/remotelogging/__init__.py,sha256=DEmzWGadTT9-utyEAAmyVDkWFhsonY4wbWIy1J34C14,245
|
|
31
|
-
qena_shared_lib/remotelogging/_base.py,sha256=
|
|
39
|
+
qena_shared_lib/remotelogging/_base.py,sha256=XykbHFzzZ7oqUFeuLDUkw1cqkjqzzOt6Cg8hR8aLzDc,15539
|
|
32
40
|
qena_shared_lib/remotelogging/logstash/__init__.py,sha256=-sg2V8gYuAKtnHSXfLorpdu_LUB_Gpldw0pCuWIsSc0,186
|
|
33
|
-
qena_shared_lib/remotelogging/logstash/_base.py,sha256=
|
|
41
|
+
qena_shared_lib/remotelogging/logstash/_base.py,sha256=GCO3P6RSiJO-LT4FIPawPSkjFDt9FZYetl09txQrwpQ,1015
|
|
34
42
|
qena_shared_lib/remotelogging/logstash/_http_sender.py,sha256=2PUZ526zzLiP6wfW6AeVfzm3qowv5KpHYXMgkd6xrn0,1776
|
|
35
43
|
qena_shared_lib/remotelogging/logstash/_tcp_sender.py,sha256=s7oW7ovYq8OHqN8tF4rXhPK9knCHx5Dsx5Bu_p4XerQ,2455
|
|
36
|
-
qena_shared_lib
|
|
37
|
-
qena_shared_lib
|
|
38
|
-
qena_shared_lib
|
|
44
|
+
qena_shared_lib/scheduler.py,sha256=Spp5PnpFJ0U4aLeFCNmje9zUA4zwkL-b7X8SSGkGssM,13579
|
|
45
|
+
qena_shared_lib/security.py,sha256=RAXBkfhytJl-2SOXYQTJMnUb789-8DNZKRjRtpod16Y,6372
|
|
46
|
+
qena_shared_lib/sync.py,sha256=79aGGWGYg_oGY9jTav1kghD8BSRY-_oNYdx3tuExr20,2541
|
|
47
|
+
qena_shared_lib/utils.py,sha256=crD8NJD1Se7ZHPCaQBCi3c7Y46lMvk8OsN_bZTbcyto,1184
|
|
48
|
+
qena_shared_lib-0.1.20.dist-info/WHEEL,sha256=k57ZwB-NkeM_6AsPnuOHv5gI5KM5kPD6Vx85WmGEcI0,78
|
|
49
|
+
qena_shared_lib-0.1.20.dist-info/METADATA,sha256=NXMw-mncYxD5lp76H1gsdJpqoOTmwYldBIkxyXMYNfo,19281
|
|
50
|
+
qena_shared_lib-0.1.20.dist-info/RECORD,,
|