Package: fastapi-event-emitter
FastAPI eventHow to useInject theevent_emitterinto Service dependencies to use# user_service.pyfromfastapi_eventimportget_event_emitterclassUserService:def__init__(self,event_emitter=get_event_emitter()):self.event_emitter=event_emitterasyncdefdeactivate_user(self,user:UserEntity):awaitself.user_repo.update_by_id(user.id,data={'deactivated_at':datetime.datetime.utcnow()})awaitself.event_emitter.emit(UserEvent.DEACTIVATED,user.id)Createobserverfile to listeneventand handle it# users/observers/user_observer.pyfromfastapi_eventimportobserver,event@observer('user:*')classUserObserver:def__init__(self,notification_service:NotificationService=Depends()):self.notification_service=notification_service@event(UserEvent.DEACTIVATED)asyncdefhandle_user_deactivated_for_related_user_tasks(self,user_id:UUID):# Add logic hereIf we need to update user related jobs in another module, we should create theUserObserverin that module followed bymodular basedtoo
Such as, we need to update caches of user posts# posts/observers/user_observer.pyfromfastapi_eventimportobserver,event@observer('user:*')classUserObserver:@event(UserEvent.DEACTIVATED)asyncdefhandle_user_deactivated_for_related_post_tasks(self,user_id:UUID):awaitqueue.add_to_queue(PostTask.CACHE_COUNT_COMMENT,user_id)CaveatCurrently, the @observer has a limitation that when I inject a service
and that service's dependencies are injected with an event_emitter, it will encounter an erjor.Right now, to fix this issue we should move the affected service to a separate one without injecting the event_emitter,
or directly importing the repository to execute the queries.It happens because we need to collect all theobserverclass before injecting theevent_emitterdependency inside that service.Example:Let's say we have a feature calleddeactivated user. We will emit thedeactivate_userevent then handle it in theobserverInside theobserverafter hanlding what needes to be done, we will push notification to user to force them logout
To do that, we want to inject theNotificationService, inside theNotificationServicedependencies we have some other tasks
that need to inject theMediaService.The issue happens here. TheMediaServicedependencies we inject theevent_emitterthat will lead to the restobserverswill never collect any__Observerclass anymore.# media_service.pyfromfastapi_eventimportget_event_emitterclassMediaService:def__init__(self,event_emitter=get_event_emitter()),):self.media_service=media_serviceasyncdefcreate(self):# Logic# notification_service.pyclassNotificationService:def__init__(self,media_service:MediaService=Depends()):self.media_service=media_serviceasyncdefemit(self):# Logic# users/observers/user_observer.pyfromfastapi_eventimportobserver,event@observer('user:*')classUserObserver:def__init__(self,notification_service:NotificationService=Depends()):self.notification_service=notification_service@event(UserEvent.DEACTIVATED)asyncdefhandle_user_deactivated_for_related_user_tasks(self,user_id:UUID):# Add logic hereTo temporarily resolve this issue, we have 2 ways:Try to not injectMediaServiceinside theNotificationServiceMove theNotificationServicemethod inside theUserObserverand inject thenotification_repodirectlyHow to test in testpypiIncrease the version inpyproject.tomlRun command$../build_and_test.shHow to publish new versionIncrease the version inpyproject.tomlRun command$../build_and_publish.sh