-
Notifications
You must be signed in to change notification settings - Fork 0
Add postgresql READ\WRITE routing #915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds PostgreSQL master-replica read/write routing functionality to support database scalability. The implementation introduces a custom routing session that directs write operations to the master database while allowing read operations to use a replica database.
Changes:
- New database routing infrastructure with
RoutingSessionclass that routes database operations between master and replica - Configuration options for single or master-replica database modes
- Master database availability checks added to all write API endpoints
- Error handling for database unavailability with OperationalError suppression and user-facing error responses
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| app/database.py | New file implementing RoutingSession for master-replica routing and engine configuration |
| app/config.py | Added replica database configuration fields and removed engine property from Settings |
| app/ioc.py | Modified session factory to support routing mode, removed engine provider |
| app/api/utils.py | New utility function to check master database availability before write operations |
| app/multidirectory.py | Updated to use engines dictionary instead of settings.engine |
| tests/conftest.py | Updated test configuration to use engines dictionary |
| app/ldap_protocol/ldap_requests/base.py | Added RESPONSE_TYPE class variable and OperationalError handling in request handlers |
| app/ldap_protocol/ldap_requests/*.py | Added RESPONSE_TYPE class variable to request classes |
| app/ldap_protocol/ldap_requests/bind.py | Added OperationalError suppression for user login attribute updates |
| app/ldap_protocol/session_storage/repository.py | Added OperationalError suppression for session key creation |
| app/api/**/router*.py | Added check_master_db dependency to write endpoints |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0cbb784 to
7891162
Compare
…nations and MFA callback
…pdate session handling
…ndencies across routers
Задача 1161
Изменения:
Settingsдобавлены:Engineпод реплику.single\replication.EngineRegistry, который включает в себяengineмастера и реплики.RoutingSession, отнаследованный отSession. В классе переопределены два метода:get_bind- метод, к которому обращается сессия перед выполнением запроса в базу (в момент вызовов.flush(),.execute(),.scalarsи т.д.) для получения бинда -EngineилиConnection.flush- в метод добавлено выставление дополнительного флага_force_masterдля чтения после записи.RESPONSE_TYPE(новый ClassVar для реквестов) нашего запроса со статус кодомLDAPCodes.UNAVAILABLE.Новый flow:
single- одна база и для чтения и для записи, то ничего не меняется, RoutingSession не используется.replication- то во время каждого запроса в базу мы в методеget_bindопределяем в каком мы сейчас состоянии сессии:_force_master, отдаем движок мастера._force_masterуже выставлен, значит отдаем движок мастера. (Например, случай Modify запроса, мы сначала выполняем запросы поиска в реплику, после этого выполняем flush для новой директории и в дальнейшем чтение в рамках запроса идет только из мастера)Открытые вопросы
sessionвioc? - там происходитsession.commit(). Если нам прилетитModifyзапрос во время отвала мастера мы упадем в.handleметоде с эксепшеномOperationalError, оно обработается выше в методе_handle_tcp\_handle_apiвbase.pyи LDAP нормально вернет ответ клиенту со статус кодомLDAPCodes.UNAVAILABLE, но при этом выйдет исключение вioc.pyуже после возвращения ответа клиенту. В целом не влияет на работу, но нужно как-то захендлить.