Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@duongphuhiep
Copy link
Collaborator

@duongphuhiep duongphuhiep commented Nov 11, 2024

The first commit add the Module feature

customContainer := ore.NewContainer()
ore.RegisterLazyFuncToContainer(customContainer, ore.Singleton, ..)
broker, _ := ore.GetFromContainer[*Broker](customContainer, ctx)

motivation:

  • for our users: support Modular Monolith architecture.
  • for us: reduce the global space
  • for us: facilitate writing isolate tests or benchmark (which can be run evens in paralellel)

The second commit add the Place Holder feature

This feature has the potential to become one of the most useful feature (or added value) of Ore.

Problem the feature will solve:

your certain Service depends on certain UserInfo (user name, user's role...), but you don't have them on registration time. Only after parsing the user request, connect to the database... that you will know the user's name, his role...

Because you cannot register a specific UserInfo directly so a common work around is to Register a UserInfoProvider instead.
As a result you have to make your Service depends on the UserInfoProvider while the real dependency is UserInfo.

A common implementation of the UserInfoProvider is to provide the UserInfo to the request context, so that it will be retreived later to create the Service => this common implementation repeat exactly what Ore is doing.

With the "place holder feature", you no longer need a UserInfoProvider "proxy". Your service depends directly to the UserInfo (as it should).

We can also think of this feature as eagerly registering an object but with Scoped life time similar to RegisterEagerSingleton

checkout the README for more info

Inspiration source:

other bug fix (second commit)

  • fix validate lifetime bug which cause flaky tests
  • fix "simple" examples

@duongphuhiep
Copy link
Collaborator Author

I will take care of the conflicts

- reduce the global surface
- possibility to create 1 container per test case, then run them in parallel
- fix validate lifetime bug which cause flaky tests
- fix "simple" examples
@sonarqubecloud
Copy link

@duongphuhiep
Copy link
Collaborator Author

duongphuhiep commented Nov 12, 2024

While resolving the conflicts, I reviewed the last commit and got some remarks

"isBuilt" and "isSealed" is quite confusing in the last commit.

I understand the idea that if the container validation was a success then it is useless to check validation over and over again for future services resolving.

While it is true most of time, exception exist for users who don't follow our recommendation:

RegisterLazyFunc(Scoped, func(ctx context.Context) (*A, context.Context) {
  if (randomNumber is odd) {
    b1, ctx = Get[*B1](ctx) //A (sometimes) depends on B1
    return &A{b1}, ctx
  } else {
    b2, ctx = Get[*B2](ctx) //A (sometimes) depends on B2 => circular dependency here
    return &A{b2}, ctx
  }
})

This guy ignores our recommendation. He put some small "if" in the resolver, making A sometimes depend on B1, sometimes depends on B2. The container's validation success, but he still not confident that his dependency graph is good. So he doesn't want to disable the runtime validation, but unfortunately it is automatically disabled with the isSealed boolean of this commit.

Naming

  • Build() doesn't really built anything, but to seal the registrations => I suggest to name it SealRegistration(), DoneRegistration(), FinishRegistration() so that the function name is self-explanatory

  • if you still want to keep the isSealed boolean, then I would suggest to replace it with an enum RegistrationsHealth { Healthy, Unknow }

    • RegistrationsHealth is set to Healthy only if the registration is sealed (no more registration) and the validation passed.
    • Evens the validation passed with success, the "registrations health" of the container stays "unknow" if the registration is still open to accept more registration.

While the enum RegistrationsHealth with 2 values technically can be map to a boolean. But reasoning the enum RegistrationsHealth makes a clearer semantic than a boolean isSealed true / false

Avoid repeating logics

the following logics appeared multiple times

if !isSealed && !DisableValidation 

it deserves to have a function

func shouldValidate() bool {
  return !isSealed && !DisableValidation 
}

@firasdarwish
Copy link
Owner

hi @duongphuhiep
thank you for your contributions, it really did add to Ore, i had finished earlier a feature that practically did multiple containers(modules) but never merged it, i will showcase the differences later and show it to you before merging if you're interested. would you be interested in becoming a maintainer when v1.0 is published ?
+
i agree with your remarks on my latest commit, i'll take care of it and do some refactoring

@firasdarwish firasdarwish merged commit aeb9fe1 into firasdarwish:main Nov 12, 2024
4 checks passed
@duongphuhiep
Copy link
Collaborator Author

thanks for your trust, I would gladly listen to your idea about "module" and help to maintain the project.

as for v1, I will open a new discussion thread for various points I can think of

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants