From 5d03dc9b5d574b0f111f2bb77f718956b77e7664 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Tue, 26 Dec 2023 18:56:15 +0700 Subject: [PATCH 1/2] fix(reminder): decrement limit properly --- reminder/handler.go | 9 ++++++- reminder/user_limiter.go | 44 +++++++++++++++++++++++++++++++++-- reminder/user_limiter_test.go | 16 ++++++++++++- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/reminder/handler.go b/reminder/handler.go index 6ff0306..93c7d0c 100644 --- a/reminder/handler.go +++ b/reminder/handler.go @@ -132,6 +132,11 @@ func (d *Dependency) Handler(ctx context.Context, c tb.Context) error { go func(c tb.Context, reminder Reminder) { time.Sleep(time.Until(reminder.Time)) + ctx := sentry.SetHubOnContext(context.Background(), sentry.CurrentHub()) + span := sentry.StartSpan(ctx, "reminder.trigger", sentry.WithTransactionName("Reminder Trigger"), sentry.WithTransactionSource(sentry.SourceTask)) + defer span.Finish() + ctx = span.Context() + template := fmt.Sprintf( "Hi %s! I'm reminding you to %s. Have a great day!", strings.Join(reminder.Subject, ", "), @@ -141,9 +146,11 @@ func (d *Dependency) Handler(ctx context.Context, c tb.Context) error { if err != nil { sentry.GetHubFromContext(ctx).CaptureException(err) } + + err = d.DecrementUserLimit(ctx, c.Sender().ID) }(c, reminder) - err = d.IncrementUserLimit(ctx, c.Sender().ID, reminderCount+1) + err = d.IncrementUserLimit(ctx, c.Sender().ID) if err != nil { sentry.GetHubFromContext(ctx).CaptureException(err) } diff --git a/reminder/user_limiter.go b/reminder/user_limiter.go index 2f7a3ab..7c684b9 100644 --- a/reminder/user_limiter.go +++ b/reminder/user_limiter.go @@ -26,11 +26,51 @@ func (d *Dependency) CheckUserLimit(ctx context.Context, id int64) (n int, err e return strconv.Atoi(string(value)) } -func (d *Dependency) IncrementUserLimit(ctx context.Context, id int64, value int) error { +func (d *Dependency) IncrementUserLimit(ctx context.Context, id int64) error { span := sentry.StartSpan(ctx, "reminder.increment_user_limit") defer span.Finish() - err := d.memory.Set(fmt.Sprintf("reminder:user_limit:%d", id), []byte(strconv.Itoa(value))) + value, err := d.memory.Get(fmt.Sprintf("reminder:user_limit:%d", id)) + if err != nil && !errors.Is(err, bigcache.ErrEntryNotFound) { + return fmt.Errorf("acquiring value from memory: %w", err) + } + + if value == nil || string(value) == "" { + value = []byte("0") + } + + i, err := strconv.Atoi(string(value)) + if err != nil { + return fmt.Errorf("invalid value: %s", value) + } + + err = d.memory.Set(fmt.Sprintf("reminder:user_limit:%d", id), []byte(strconv.Itoa(i+1))) + if err != nil { + return fmt.Errorf("setting value to memory: %w", err) + } + + return nil +} + +func (d *Dependency) DecrementUserLimit(ctx context.Context, id int64) error { + span := sentry.StartSpan(ctx, "reminder.decrement_user_limit") + defer span.Finish() + + value, err := d.memory.Get(fmt.Sprintf("reminder:user_limit:%d", id)) + if err != nil && !errors.Is(err, bigcache.ErrEntryNotFound) { + return fmt.Errorf("acquiring value from memory: %w", err) + } + + if value == nil || string(value) == "" { + value = []byte("0") + } + + i, err := strconv.Atoi(string(value)) + if err != nil { + return fmt.Errorf("invalid value: %s", value) + } + + err = d.memory.Set(fmt.Sprintf("reminder:user_limit:%d", id), []byte(strconv.Itoa(i-1))) if err != nil { return fmt.Errorf("setting value to memory: %w", err) } diff --git a/reminder/user_limiter_test.go b/reminder/user_limiter_test.go index 77a92bd..f450912 100644 --- a/reminder/user_limiter_test.go +++ b/reminder/user_limiter_test.go @@ -35,7 +35,7 @@ func TestUserLimit(t *testing.T) { t.Errorf("expecting userLimit to be 0, instead got %d", userLimit) } - err = dependency.IncrementUserLimit(ctx, 123, 1) + err = dependency.IncrementUserLimit(ctx, 123) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -48,4 +48,18 @@ func TestUserLimit(t *testing.T) { if userLimit2 != 1 { t.Errorf("expecting userLimit2 to be 1, instead got %d", userLimit2) } + + err = dependency.DecrementUserLimit(ctx, 123) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + userLimit3, err := dependency.CheckUserLimit(ctx, 123) + if err != nil { + t.Errorf("unexpected error: %s", err.Error()) + } + + if userLimit3 != 0 { + t.Errorf("expecting userLimit3 to be 0, instead got %d", userLimit2) + } } From 25c044746d9ce700de264e1c512abf722644fd5d Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Tue, 26 Dec 2023 19:01:13 +0700 Subject: [PATCH 2/2] fix(reminder): handle error for decrement --- reminder/handler.go | 3 +++ reminder/user_limiter.go | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/reminder/handler.go b/reminder/handler.go index 93c7d0c..ee788d6 100644 --- a/reminder/handler.go +++ b/reminder/handler.go @@ -148,6 +148,9 @@ func (d *Dependency) Handler(ctx context.Context, c tb.Context) error { } err = d.DecrementUserLimit(ctx, c.Sender().ID) + if err != nil { + sentry.GetHubFromContext(ctx).CaptureException(err) + } }(c, reminder) err = d.IncrementUserLimit(ctx, c.Sender().ID) diff --git a/reminder/user_limiter.go b/reminder/user_limiter.go index 7c684b9..46259a0 100644 --- a/reminder/user_limiter.go +++ b/reminder/user_limiter.go @@ -62,7 +62,8 @@ func (d *Dependency) DecrementUserLimit(ctx context.Context, id int64) error { } if value == nil || string(value) == "" { - value = []byte("0") + // Don't decrement anything that's empty + return nil } i, err := strconv.Atoi(string(value))