feat: [SUB-786] Add WithProviders function#1236
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds a WithProviders function to the ApplicationBuilder interface, enabling registration of custom service providers during application initialization. The changes also reorganize the codebase by moving the ApplicationBuilder interface to its own file.
- Adds
WithProvidersmethod to register service providers - Moves
ApplicationBuilderinterface fromapplication.goto dedicatedapplication_builder.gofile - Implements the new method in the concrete
ApplicationBuildertype
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| contracts/foundation/application_builder.go | New file containing the ApplicationBuilder interface with the added WithProviders method |
| contracts/foundation/application.go | Removed ApplicationBuilder interface (moved to separate file) |
| foundation/application_builder.go | Implements WithProviders method for the ApplicationBuilder struct |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1236 +/- ##
==========================================
+ Coverage 65.73% 67.66% +1.92%
==========================================
Files 248 250 +2
Lines 17185 14109 -3076
==========================================
- Hits 11297 9547 -1750
+ Misses 5511 4180 -1331
- Partials 377 382 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
hwbrzzl
left a comment
There was a problem hiding this comment.
Pretty good 💯 Only a few nitpicks
| loaded bool | ||
| } | ||
|
|
||
| func NewProviderRepository() *ProviderRepository { |
There was a problem hiding this comment.
| func NewProviderRepository() *ProviderRepository { | |
| func NewProviderRepository(app foundation.Application) *ProviderRepository { |
There was a problem hiding this comment.
Passing a struct-level parameter for this felt confusing to me, specifically, the fact that
Application accepts a ProviderRepository, and ProviderRepository in turn accepts an Application in constructor. And given that we only need the app for passing it to the service provider during Register and Boot.
That kind of circular dependency feels odd.
type Application struct {
*Container
ctx context.Context
cancel context.CancelFunc
providerRepository foundation.ProviderRepository
publishes map[string]map[string]string
publishGroups map[string]map[string]string
json foundation.Json
}
type ProviderRepository struct {
app foundation.ServiceProvider
states map[string]*ProviderState
providers []foundation.ServiceProvider
sorted []foundation.ServiceProvider
sortedValid bool
loaded bool
}There was a problem hiding this comment.
Agree about odd, LoadFromConfig can be optimized, config can be passed via NewProviderRepository .
There was a problem hiding this comment.
But we still need the app in the Register and Boot methods, so I'm not sure if it's even necessary to accept config in constructor.
There was a problem hiding this comment.
The config facade is optional, and this method (LoadFromConfig) may be removed in a future version when we deprecate setting providers through the config.
There was a problem hiding this comment.
Yes, but passing config is more reasonable than app.
There was a problem hiding this comment.
Yeah, we can accept config, but my only concern is whether it’s unnecessary to take it as a constructor parameter. We could just accept config in LoadFromConfig instead of app. What do you think?
There was a problem hiding this comment.
Em, I think we can add a constructor parameter directly, it's consistent with other modules.
There was a problem hiding this comment.
I think there is one more issue with adding it in constructor param:
func init() {
setEnv()
setRootPath()
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
app := &Application{
Container: NewContainer(),
ctx: ctx,
cancel: cancel,
publishes: make(map[string]map[string]string),
publishGroups: make(map[string]map[string]string),
}
app.providerRepository = NewProviderRepository() // I will need to call app.MakeConfig() will will return an error since config service provider is not booted yet, will that be an issue here?
App = app
baseProviders := app.getBaseServiceProviders()
app.providerRepository.Add(baseProviders)
app.providerRepository.Register(app)
app.providerRepository.Boot(app)
app.SetJson(json.New())
}There was a problem hiding this comment.
Good catch, makes sense, we have to pass the config to the LoadFromConfig function due to this.
There was a problem hiding this comment.
⚠️ Performance Alert ⚠️
Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.
| Benchmark suite | Current: 733cd85 | Previous: c1347c3 | Ratio |
|---|---|---|---|
Benchmark_EncryptString |
4330 ns/op 2152 B/op 14 allocs/op |
1550 ns/op 2152 B/op 14 allocs/op |
2.79 |
Benchmark_EncryptString - ns/op |
4330 ns/op |
1550 ns/op |
2.79 |
This comment was automatically generated by workflow using github-action-benchmark.
hwbrzzl
left a comment
There was a problem hiding this comment.
Thanks, LGTM except one tip.
📑 Description
closes goravel/goravel#790
This PR makes the following changes:
ApplicationBuildercontracts to its own file, asapplication.gois getting too long.ProviderRepositoryto manage all provider-related operations (sorting, registration, booting, cycle detection, etc.).Applicationto delegate all provider logic to the newProviderRepository, makingapplication.gomuch cleaner and simpler.ProviderRepositoryinterface for decoupling and easier testing.ApplicationBuilderto use the newApplication.SetConfiguredProvidershook.Note
Currently, this PR won't change how
package:installregisters providers; it will still use theapp.providerskey in the config. I will optimize that in a different PR.Usage-wise, there is not much change, but it does introduce the new
WithProvidersmethod, which can now be used withfoundation.Configure():✅ Checks