Service container
I 'service container' sono potenti strumenti in grado di gestire le dipendenze del nostro applicativo.
È possibile pensare ad un 'service container' come ad un contenitore dove al suo interno le dipendenze vengono risolte automaticamente. Questo significa che tutti i metodi che vengono eseguiti all'interno questo contesto possono accedere a queste dipendenze.
Gli step necessari per utilizzare questo strumento sono:
- Definire un servizio
- Registrarlo all'interno dello specifico container.
Definizione di un servizio
Tutti i servizi devono essere definiti all'interno del pacchetto service e consistono in un metodo che restituisce un oggetto ti uno specifico tipo.
package service
import (
"fmt"
"github.com/shahind/go-jet/config"
"github.com/go-redis/redis/v7"
"github.com/labstack/gommon/log"
)
// ConnectRedis connect to Redis
func ConnectRedis() *redis.Client {
conf := config.GetRedis()
client := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", conf.Host, conf.Port),
Password: conf.Password,
DB: 1,
})
_, err := client.Ping().Result()
if err != nil {
log.Error(err)
}
return client
}
L'esempio di codice mostra come dovrebbe essere definito un servizio.
Possiamo notare che il metodo ConnectRedis() restituisce un oggetto di tipo *redis.Client che, una volta registrato all'interno del service container, permetterà a controller e comandi di risolvere la dipendenza in automatico.
Registrazione di un servizio
Per poter registrare un servizio all'interno di un service container è necessario inserire il metodo creato in precedenza all'interno della struttura foundation.BaseEntities situate nel pacchetto register.
package register
import (
"github.com/shahind/go-jet-framework"
"github.com/shahind/go-jet-framework/register"
"github.com/shahind/go-jet/app/console"
"github.com/shahind/go-jet/app/http/controller"
"github.com/shahind/go-jet/database/model"
"github.com/shahind/go-jet/router"
"github.com/shahind/go-jet/service"
)
func BaseEntities() foundation.BaseEntities {
return foundation.BaseEntities{
// ... other entities ...
Services: register.ServiceRegister{
service.ConnectDB,
service.ConnectElastic,
service.ConnectMongo,
service.ConnectRedis, // <- registrazione del servizio 'Redis'
},
SingletonServices: register.ServiceRegister{},
CommandServices: console.Services,
// ... other entities ...
}
}
Come è possibile notare, il servizio può essere registrato in tre modi:
- All'interno del campo
Services - All'interno del campo
SingletonServices - Popolando la struttura
console.Services
Services
Rappresenta il service container generato ad ogni richiesta in arrivo. Le dipendenze risolte al suo interno vengono rigenerate ogni volta che viene presa un carico una nuova richiesta.
SingletonServices
Rappresenta un service container che viene generato una sola volta all'avvio dell'applicazione. Tutte le dipendenze risolte al suo interno vengono generato all'avvio dell'applicazione.
Tutti gli utilizzatori di questo service container utilizzeranno la stessa istanza.
CommandServices
Consiste nel service container utilizzato da tutti i comandi eseguiti da CLI.
È possibile configurare i servizi disponibili andando ad implementare la struttura console.Services presente all'interno del paccheto console.
package console
import (
"github.com/shahind/go-jet-framework/register"
"github.com/shahind/go-jet/service"
)
var (
// Commands is used to register all console commands.
Commands = register.CommandRegister{}
// Services will be used to create the Console Service Container.
// This container is created to allow dependency injection through console commands.
Services = register.ServiceRegister{
service.ConnectDB,
service.ConnectElastic,
service.ConnectMongo,
service.ConnectRedis,
// ... OTHER SERVICES ...
}
)
Utilizzo dei container
Una volta configurati i servizi possono essere consumati all'interno di un container o da un comando eseguito da CLI. Basterà inserire il tipo di oggetto ritornato dal servizio come:
- Parametro del metodo
Run()del comando - Parametro dei metodi presenti all'interno dei controller.
// Dependency injection in controller
package controller
import (
"github.com/shahind/go-jet-framework"
"github.com/shahind/go-jet/database/model"
"github.com/jinzhu/gorm"
)
type SampleController struct{
gwf.BaseController
}
// Main controller method
func (c *SampleController) Main(db *gorm.DB) {
// Il parametro `db *gorm.DB` è iniettato
// all'interno del controller tramite il service container
var user model.User
if err := db.Find(&user).Error;err != nil {
gwf.ProcessError(err)
}
}
package console
type Batman struct {
Signature string
Description string
Args string
}
// Command registration
func (c *Batman) Register() {
c.Signature = "command:signature" // Change command signature
c.Description = "Execute database seeder" // Change command desc
}
// Command business logic
func (c *Batman) Run(db *gorm.DB) {
// Il parametro `db *gorm.DB` è iniettato
// all'interno del controller tramite il service container
var user model.User
if err := db.Find(&user).Error;err != nil {
gwf.ProcessError(err)
}
}