Skip to content
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

Subgraphs #68

Closed
Tishka17 opened this issue Feb 22, 2024 · 1 comment · Fixed by #80
Closed

Subgraphs #68

Tishka17 opened this issue Feb 22, 2024 · 1 comment · Fixed by #80
Labels
enhancement New feature or request
Milestone

Comments

@Tishka17
Copy link
Collaborator

Tishka17 commented Feb 22, 2024

Use case:
Interactor depends on StatisticDbGateway and MainDbGateway. Each of them uses SQLAlchemy Session object, so they have similar init typehints. The difference is that StatisticDbGateway requires Session bound to Clickhouse Engine, while MainDbGateway binds to postgresql Engine. Again both engines have same type, but created differently.

To solve this you can replace Session with some new type (literally NewType("PgSession", Session)), but it requires modification of all code base. Imagine that you took those objects from external library and cannot modify it.

Another solution is again to use NewType, but create factories for all objects instead of registrering classes as depedencies directly. This requries a lot of work.

Proposed solution is to split those objects in 3 groups:

SubGraph1: StatisticDbGateway, Session, Engine
SubGraph2: MainDbGateway, Session, Engine
MainGraph: Interactor, SubGraph1, SubGraph2

Each graph here uses only his factories to solve dependencies or requests specially attached subgraphs. So here, gateways can request Session and they get exactly that session which is declared in his subgraph.

Requirements:

  1. (Sub)graphs can have subgraphs
  2. All (Sub)graphs are synchronized by scopes
  3. Subgraph cannot access depedencies from parent graph
  4. When looking for factories subgraphs are requested only if they are not found in current graph itself.

It is an open question whether (sub)graph is just a container or another thing

@Tishka17 Tishka17 added the enhancement New feature or request label Feb 22, 2024
@Tishka17 Tishka17 added this to the 1.0 milestone Feb 24, 2024
@Tishka17
Copy link
Collaborator Author

The idea: components

On container creation you need somehow attatch providers to component names. It can be either provider attribute, or separate object or just a dictionary. E.g.

make_container(
   components={
      "": [provider1],
      "C1": [provider2, provider3],
   },
)

What's the effect?

Logic of .get:

  • When user calls .get(Class) he receives an object from default ("") component.
  • Whe user calls .get(Class, component="C1"), he receives an object from compo1nent named "C1"

Factory dependencies:

  • By default objects required by a factory a looked up within the same component
  • You can specify Annotated[Class, FromComponent("C1"))] to change lookup component to "C1"

If we want to make all factories from component X to receive Class objects from component "C1" we can create alias: alias(Class, component="C1")

Depends will have component attribute as well.

How does it work?

  1. We still have single container, so there is not problem of synchronizing scopes between subgraphs
  2. We changer dependency key from just type to a pair (type, component)
  3. All internal calls like _get_unlicked will receive that composite depenency key. .get will require type and optional component.
  4. Factory dependencies will be those keys as well instead of just types.

What to notify?
We want to reuse same provider with multiple components because part of multiple subgraphs can be the same

This was referenced Feb 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant