You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
6.3 KiB
Go
298 lines
6.3 KiB
Go
package settings
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"go-micro.dev/v4/errors"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
"jochum.dev/jo-micro/auth2"
|
|
"jochum.dev/jo-micro/components"
|
|
"jochum.dev/jo-micro/settings/cmd/microsettingsd/config"
|
|
"jochum.dev/jo-micro/settings/proto/settingspb"
|
|
"jochum.dev/jo-micro/settings/utils"
|
|
)
|
|
|
|
const Name = "settingsClient"
|
|
|
|
type Handler struct {
|
|
initialized bool
|
|
cReg *components.Registry
|
|
cacheGetLock *sync.RWMutex
|
|
cacheGet map[string]*Setting
|
|
cacheListLock *sync.RWMutex
|
|
cacheList map[string][]*Setting
|
|
}
|
|
|
|
func MustReg(cReg *components.Registry) *Handler {
|
|
return cReg.Must(Name).(*Handler)
|
|
}
|
|
|
|
func (h *Handler) client(ctx context.Context) (settingspb.SettingsService, context.Context, error) {
|
|
// Wait until the service is here
|
|
_, err := utils.ServiceRetryGet(h.cReg.Service(), config.Name, 10)
|
|
if err != nil {
|
|
return nil, ctx, err
|
|
}
|
|
|
|
service := settingspb.NewSettingsService(config.Name, h.cReg.Service().Client())
|
|
|
|
// Optional Service Account
|
|
if err := auth2.RegHasClientAuth(h.cReg); err == nil {
|
|
ctx, err = auth2.ClientAuthMustReg(h.cReg).Plugin().ServiceContext(ctx)
|
|
if err != nil {
|
|
return nil, ctx, err
|
|
}
|
|
}
|
|
|
|
return service, ctx, nil
|
|
|
|
}
|
|
|
|
// NewLog creates a new component
|
|
func New() *Handler {
|
|
return &Handler{
|
|
initialized: false,
|
|
cacheGetLock: &sync.RWMutex{},
|
|
cacheGet: make(map[string]*Setting),
|
|
cacheListLock: &sync.RWMutex{},
|
|
cacheList: make(map[string][]*Setting),
|
|
}
|
|
}
|
|
|
|
func (c *Handler) Priority() int {
|
|
return 30
|
|
}
|
|
|
|
func (c *Handler) Name() string {
|
|
return Name
|
|
}
|
|
|
|
func (c *Handler) Flags(cReg *components.Registry) []cli.Flag {
|
|
return []cli.Flag{
|
|
&cli.IntFlag{
|
|
Name: fmt.Sprintf("%s_settings_cachetime", strings.ToLower(cReg.FlagPrefix())),
|
|
Usage: "Time in seconds where settings caches your request",
|
|
Value: 3600,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *Handler) Initialized() bool {
|
|
return c.initialized
|
|
}
|
|
|
|
func (h *Handler) Init(cReg *components.Registry, cli *cli.Context) error {
|
|
if h.initialized {
|
|
return errors.InternalServerError("ALREADY_INITIALIZED", "already initialized")
|
|
}
|
|
|
|
h.cReg = cReg
|
|
|
|
h.initialized = true
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) Stop() error {
|
|
h.initialized = false
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) Health(context context.Context) error {
|
|
if !h.Initialized() {
|
|
return errors.InternalServerError("NOT_INITIALIZED", "not initialized")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *Handler) Get(ctx context.Context, id, ownerId, service, name string) (*Setting, error) {
|
|
// Build the request
|
|
req := &settingspb.GetRequest{}
|
|
cacheKey := ""
|
|
if len(id) > 0 {
|
|
req.Id = id
|
|
cacheKey = id
|
|
} else if len(ownerId) > 0 {
|
|
req.OwnerId = ownerId
|
|
if len(name) > 0 {
|
|
req.Name = name
|
|
cacheKey = fmt.Sprintf("%s-%s", req.OwnerId, req.Name)
|
|
} else {
|
|
cacheKey = req.OwnerId
|
|
}
|
|
} else if len(service) > 0 {
|
|
req.Service = service
|
|
if len(name) > 0 {
|
|
req.Name = name
|
|
cacheKey = fmt.Sprintf("%s-%s", req.Service, req.Name)
|
|
} else {
|
|
cacheKey = req.Service
|
|
}
|
|
} else {
|
|
return nil, errors.BadRequest("INVALID_ARGUMENTS", "invalid arguments")
|
|
}
|
|
|
|
// Check cache and return from cache
|
|
h.cacheGetLock.RLock()
|
|
if result, ok := h.cacheGet[cacheKey]; ok {
|
|
h.cacheGetLock.RUnlock()
|
|
return result, nil
|
|
}
|
|
h.cacheGetLock.RUnlock()
|
|
|
|
client, ctx, err := h.client(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result, err := client.Get(ctx, req)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s: %s", cacheKey, err)
|
|
}
|
|
|
|
cResult, err := serviceToClient(result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Store the result in cache
|
|
h.cacheGetLock.Lock()
|
|
h.cacheGet[cacheKey] = cResult
|
|
h.cacheGetLock.Unlock()
|
|
|
|
return cResult, nil
|
|
}
|
|
|
|
func (h *Handler) List(ctx context.Context, id, ownerId, service, name string) ([]*Setting, error) {
|
|
// Build the request
|
|
req := &settingspb.ListRequest{}
|
|
cacheKey := ""
|
|
if len(id) > 0 {
|
|
req.Id = id
|
|
cacheKey = id
|
|
} else if len(service) > 0 {
|
|
req.Service = service
|
|
if len(name) > 0 {
|
|
req.Name = name
|
|
cacheKey = fmt.Sprintf("%s-%s", req.Service, req.Name)
|
|
} else {
|
|
cacheKey = req.Service
|
|
}
|
|
} else if len(ownerId) > 0 {
|
|
req.OwnerId = ownerId
|
|
if len(name) > 0 {
|
|
req.Name = name
|
|
cacheKey = fmt.Sprintf("%s-%s", req.OwnerId, req.Name)
|
|
} else {
|
|
cacheKey = req.OwnerId
|
|
}
|
|
} else {
|
|
return nil, errors.BadRequest("INVALID_ARGUMENTS", "invalid arguments")
|
|
}
|
|
|
|
// Check cache and return from cache
|
|
h.cacheListLock.RLock()
|
|
if result, ok := h.cacheList[cacheKey]; ok {
|
|
h.cacheListLock.RUnlock()
|
|
return result, nil
|
|
}
|
|
h.cacheListLock.RUnlock()
|
|
|
|
// Fetch
|
|
client, ctx, err := h.client(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result, err := client.List(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cResult := make([]*Setting, len(result.Data))
|
|
for idx, s := range result.Data {
|
|
cS, err := serviceToClient(s)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cResult[idx] = cS
|
|
}
|
|
|
|
// Store the result in cache
|
|
h.cacheListLock.Lock()
|
|
h.cacheList[cacheKey] = cResult
|
|
h.cacheListLock.Unlock()
|
|
|
|
return cResult, nil
|
|
}
|
|
|
|
func (h *Handler) Create(ctx context.Context, req CreateRequest) (*Setting, error) {
|
|
// Create
|
|
client, ctx, err := h.client(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sReq := &settingspb.CreateRequest{
|
|
Service: req.Service,
|
|
OwnerId: req.OwnerId,
|
|
Name: req.Name,
|
|
Content: req.Content,
|
|
RolesRead: req.RolesRead,
|
|
RolesUpdate: req.RolesUpdate,
|
|
}
|
|
|
|
result, err := client.Create(ctx, sReq)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return serviceToClient(result)
|
|
}
|
|
|
|
func (h *Handler) Update(ctx context.Context, req UpdateRequest) (*Setting, error) {
|
|
// Update
|
|
client, ctx, err := h.client(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sReq := &settingspb.UpdateRequest{
|
|
Id: req.Id.String(),
|
|
Content: req.Content,
|
|
}
|
|
|
|
result, err := client.Update(ctx, sReq)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return serviceToClient(result)
|
|
}
|
|
|
|
func (h *Handler) Upsert(ctx context.Context, req UpsertRequest) (*Setting, error) {
|
|
// Upsert
|
|
client, ctx, err := h.client(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sReq := &settingspb.UpsertRequest{
|
|
Id: req.Id.String(),
|
|
OwnerId: req.OwnerId.String(),
|
|
Service: req.Service,
|
|
Name: req.Name,
|
|
|
|
Content: req.Content,
|
|
RolesRead: req.RolesRead,
|
|
RolesUpdate: req.RolesUpdate,
|
|
}
|
|
|
|
result, err := client.Upsert(ctx, sReq)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return serviceToClient(result)
|
|
}
|