name support & slight changes in business logic

This commit is contained in:
Pavel 2022-12-29 00:03:40 +03:00
parent 7bff09f467
commit 1c6689583a
4 changed files with 31 additions and 14 deletions

View File

@ -12,6 +12,7 @@ const DefaultResetPeriod = time.Minute * 15
// AtomicCounter is a default Counter implementation.
// It uses atomics under the hood (hence the name) and can be configured with custom reset timeout and
type AtomicCounter struct {
name atomic.String
msg atomic.String
timestamp atomic.Time
resetPeriod time.Duration
@ -23,16 +24,25 @@ type AtomicCounter struct {
}
// NewAtomicCounterWithPeriod returns AtomicCounter configured with provided period.
func NewAtomicCounterWithPeriod(resetPeriod time.Duration) Counter {
func NewAtomicCounterWithPeriod(name string, resetPeriod time.Duration) Counter {
c := &AtomicCounter{}
c.SetName(name)
c.resetPeriod = resetPeriod
c.timestamp.Store(time.Now())
return c
}
// NewAtomicCounter returns AtomicCounter with DefaultResetPeriod.
func NewAtomicCounter() Counter {
return NewAtomicCounterWithPeriod(DefaultResetPeriod)
func NewAtomicCounter(name string) Counter {
return NewAtomicCounterWithPeriod(name, DefaultResetPeriod)
}
func (a *AtomicCounter) Name() string {
return a.name.Load()
}
func (a *AtomicCounter) SetName(name string) {
a.name.Store(name)
}
func (a *AtomicCounter) HitSuccess() {

View File

@ -3,7 +3,8 @@ package health
// Storage stores different instances of Counter. Implementation should be goroutine-safe.
type Storage interface {
// Get counter by its ID. The counter will be instantiated automatically if necessary.
Get(id int) Counter
// Name here is not used to identify the counter in the storage.
Get(id int, name string) Counter
// Remove counter if it exists.
Remove(id int)
// Process will iterate over counters and call Processor on each of them.
@ -15,6 +16,10 @@ type Storage interface {
// is not working properly (invalid credentials, too many failed requests, etc) and take further action based on the result.
// Implementation should be goroutine-safe.
type Counter interface {
// Name can be used as a more friendly identifier for the counter.
Name() string
// SetName of the counter.
SetName(name string)
// HitSuccess registers successful request. It should automatically clear error state because that state should be
// used only if error is totally unrecoverable.
HitSuccess()
@ -55,8 +60,8 @@ type Processor interface {
// NotifyMessageLocalizer is the smallest subset of core.Localizer used in the
type NotifyMessageLocalizer interface {
SetLocale(string)
GetLocalizedMessage(string) string
SetLocale(locale string)
GetLocalizedTemplateMessage(messageID string, templateData map[string]interface{}) string
}
// NotifyFunc will send notification about error to the system with provided credentials.
@ -64,7 +69,7 @@ type NotifyMessageLocalizer interface {
type NotifyFunc func(apiURL, apiKey, msg string)
// CounterConstructor is used to create counters. This way you can implement your own counter and still use default CounterStorage.
type CounterConstructor func() Counter
type CounterConstructor func(name string) Counter
// ConnectionDataProvider should return the connection credentials and language by counter ID.
// It's best to use account ID as a counter ID to be able to retrieve the necessary data as easy as possible.

View File

@ -26,8 +26,8 @@ func (c CounterProcessor) Process(id int, counter Counter) {
return
}
apiURL, apiKey, lang := c.ConnectionDataProvider(id)
c.Notifier(apiURL, apiKey, c.getErrorText(counter.Message(), lang))
apiURL, apiKey, _ := c.ConnectionDataProvider(id)
c.Notifier(apiURL, apiKey, counter.Message())
counter.FailureProcessed()
return
}
@ -55,15 +55,15 @@ func (c CounterProcessor) Process(id int, counter Counter) {
}
apiURL, apiKey, lang := c.ConnectionDataProvider(id)
c.Notifier(apiURL, apiKey, c.getErrorText(c.Error, lang))
c.Notifier(apiURL, apiKey, c.getErrorText(counter.Name(), c.Error, lang))
counter.CountersProcessed()
return
}
func (c CounterProcessor) getErrorText(msg, lang string) string {
func (c CounterProcessor) getErrorText(name, msg, lang string) string {
if c.Localizer == nil {
return msg
}
c.Localizer.SetLocale(lang)
return c.Localizer.GetLocalizedMessage(msg)
return c.Localizer.GetLocalizedTemplateMessage(msg, map[string]interface{}{"Name": name})
}

View File

@ -15,12 +15,14 @@ func NewSyncMapStorage(constructor CounterConstructor) Storage {
return &SyncMapStorage{constructor: constructor}
}
func (s *SyncMapStorage) Get(id int) Counter {
func (s *SyncMapStorage) Get(id int, name string) Counter {
val, found := s.m.Load(id)
if found {
counter := val.(Counter)
counter.SetName(name)
return val.(Counter)
}
c := s.constructor()
c := s.constructor(name)
s.m.Store(id, c)
return c
}