runtime.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """One lazily constructed data-source manager per backend Worker process."""
  2. import threading
  3. _lock = threading.Lock()
  4. _manager = None
  5. _factory = None
  6. class _Neo4jDefinitionGateway:
  7. def _call(self, method, *args, **kwargs):
  8. from app.core.data_source.definitions import (
  9. DataSourceDefinitionRepository,
  10. )
  11. from app.services.neo4j_driver import neo4j_driver
  12. with neo4j_driver.get_session() as session:
  13. repository = DataSourceDefinitionRepository(session)
  14. return getattr(repository, method)(*args, **kwargs)
  15. def get(self, *args, **kwargs):
  16. return self._call("get", *args, **kwargs)
  17. def list(self, *args, **kwargs):
  18. return self._call("list", *args, **kwargs)
  19. def save(self, *args, **kwargs):
  20. return self._call("save", *args, **kwargs)
  21. def delete(self, *args, **kwargs):
  22. return self._call("delete", *args, **kwargs)
  23. def credential_references(self, *args, **kwargs):
  24. return self._call("credential_references", *args, **kwargs)
  25. def remove_legacy_secret_fields(self, *args, **kwargs):
  26. return self._call(
  27. "remove_legacy_secret_fields",
  28. *args,
  29. **kwargs,
  30. )
  31. def _build_default_manager():
  32. from flask import current_app
  33. from app import db
  34. from app.config.config import datasource_pool_settings
  35. from app.core.data_source.adapters import adapter_for
  36. from app.core.data_source.credentials import (
  37. CredentialCodec,
  38. DataSourceCredentialRepository,
  39. )
  40. from app.core.data_source.manager import DataSourceConnectionManager
  41. from app.core.data_source.pool_registry import PoolRegistry
  42. codec = CredentialCodec.from_base64(
  43. current_app.config.get("DATASOURCE_CREDENTIAL_MASTER_KEY", ""),
  44. current_app.config.get("DATASOURCE_CREDENTIAL_KEY_VERSION", "v1"),
  45. )
  46. base_settings = datasource_pool_settings()
  47. registry_settings = {
  48. **base_settings,
  49. "drain_timeout": 30,
  50. }
  51. certificate_dir = current_app.config.get("DATASOURCE_CERT_DIR")
  52. return DataSourceConnectionManager(
  53. definitions=_Neo4jDefinitionGateway(),
  54. credentials=DataSourceCredentialRepository(codec),
  55. platform_session=lambda: db.session,
  56. adapter_resolver=lambda database_type: adapter_for(
  57. database_type,
  58. certificate_dir=certificate_dir,
  59. ),
  60. registry=PoolRegistry(registry_settings),
  61. settings_resolver=datasource_pool_settings,
  62. )
  63. def configure_data_source_runtime(factory):
  64. """Replace the process-local factory and clear any current manager."""
  65. global _factory, _manager
  66. with _lock:
  67. if _manager is not None:
  68. _manager.close()
  69. _manager = None
  70. _factory = factory
  71. def get_data_source_manager():
  72. global _manager
  73. if _manager is not None:
  74. return _manager
  75. with _lock:
  76. if _manager is None:
  77. _manager = (_factory or _build_default_manager)()
  78. return _manager
  79. def peek_data_source_manager():
  80. """Return the current Worker manager without constructing one."""
  81. return _manager
  82. def close_data_source_runtime():
  83. global _manager
  84. with _lock:
  85. manager = _manager
  86. _manager = None
  87. if manager is not None:
  88. manager.close()