apollo-backend/internal/worker/stuck_notifications.go

218 lines
5.7 KiB
Go
Raw Normal View History

2021-10-17 14:17:41 +00:00
package worker
import (
"context"
"os"
2022-07-13 22:30:03 +00:00
"time"
2021-10-17 14:17:41 +00:00
"github.com/DataDog/datadog-go/statsd"
"github.com/go-redis/redis/v8"
"github.com/jackc/pgx/v4/pgxpool"
2022-05-23 18:17:25 +00:00
"go.uber.org/zap"
2021-10-17 14:17:41 +00:00
"github.com/christianselig/apollo-backend/internal/domain"
"github.com/christianselig/apollo-backend/internal/reddit"
"github.com/christianselig/apollo-backend/internal/repository"
)
type stuckNotificationsWorker struct {
2022-11-02 04:49:20 +00:00
logger *zap.Logger
statsd *statsd.Client
db *pgxpool.Pool
redis *redis.Client
reddit *reddit.Client
2021-10-17 14:17:41 +00:00
accountRepo domain.AccountRepository
}
2022-11-02 04:49:20 +00:00
func NewStuckNotificationsWorker(ctx context.Context, logger *zap.Logger, statsd *statsd.Client, db *pgxpool.Pool, redis *redis.Client, consumers int) Worker {
2021-10-17 14:17:41 +00:00
reddit := reddit.NewClient(
os.Getenv("REDDIT_CLIENT_ID"),
os.Getenv("REDDIT_CLIENT_SECRET"),
statsd,
2022-03-12 17:50:05 +00:00
redis,
2021-10-17 14:17:41 +00:00
consumers,
)
return &stuckNotificationsWorker{
logger,
statsd,
db,
redis,
reddit,
repository.NewPostgresAccount(db),
}
}
2022-11-02 04:49:20 +00:00
func (snw *stuckNotificationsWorker) Process(ctx context.Context, args ...interface{}) error {
2022-07-13 22:30:03 +00:00
now := time.Now()
defer func() {
elapsed := time.Now().Sub(now).Milliseconds()
2022-11-02 04:49:20 +00:00
_ = snw.statsd.Histogram("apollo.consumer.runtime", float64(elapsed), []string{"queue:stuck-notifications"}, 0.1)
2022-07-13 22:30:03 +00:00
}()
2022-11-02 05:15:25 +00:00
id := args[0].(string)
snw.logger.Debug("starting job", zap.String("account#reddit_account_id", id))
2022-05-23 18:17:25 +00:00
2022-11-02 05:15:25 +00:00
account, err := snw.accountRepo.GetByRedditID(ctx, id)
2021-10-17 14:17:41 +00:00
if err != nil {
2022-11-02 05:19:13 +00:00
snw.logger.Error("failed to fetch account from database", zap.Error(err), zap.String("account#reddit_account_id", id))
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:17:41 +00:00
}
if account.LastMessageID == "" {
2022-11-02 04:49:20 +00:00
snw.logger.Debug("account has no messages, bailing early",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:17:41 +00:00
}
2022-11-02 04:49:20 +00:00
rac := snw.reddit.NewAuthenticatedClient(account.AccountID, account.RefreshToken, account.AccessToken)
2021-10-17 14:17:41 +00:00
2022-11-02 04:49:20 +00:00
snw.logger.Debug("fetching last thing",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2021-10-17 14:17:41 +00:00
2021-10-17 14:47:43 +00:00
kind := account.LastMessageID[:2]
var things *reddit.ListingResponse
if kind == "t4" {
2022-11-02 04:49:20 +00:00
snw.logger.Debug("checking last thing via inbox",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2021-10-17 14:17:41 +00:00
2022-10-27 00:46:17 +00:00
things, err = rac.MessageInbox(ctx)
2021-10-17 14:47:43 +00:00
if err != nil {
2022-05-19 15:51:56 +00:00
if err != reddit.ErrRateLimited {
2022-11-02 04:49:20 +00:00
snw.logger.Error("failed to fetch last thing via inbox",
2022-05-23 18:17:25 +00:00
zap.Error(err),
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-05-19 15:51:56 +00:00
}
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:17:41 +00:00
}
2021-10-17 14:47:43 +00:00
} else {
2022-10-27 00:46:17 +00:00
things, err = rac.AboutInfo(ctx, account.LastMessageID)
2021-10-17 14:47:43 +00:00
if err != nil {
2022-11-02 04:49:20 +00:00
snw.logger.Error("failed to fetch last thing",
2022-05-23 18:17:25 +00:00
zap.Error(err),
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:47:43 +00:00
}
}
2021-10-17 14:53:14 +00:00
if things.Count > 0 {
2021-10-17 14:47:43 +00:00
for _, thing := range things.Children {
if thing.FullName() != account.LastMessageID {
continue
}
2022-05-19 16:37:03 +00:00
if thing.IsDeleted() {
break
}
2022-05-19 17:02:16 +00:00
if kind == "t4" {
2022-11-02 04:49:20 +00:00
return nil
2022-05-19 17:02:16 +00:00
}
2022-10-27 00:46:17 +00:00
sthings, err := rac.MessageInbox(ctx)
2022-05-19 16:37:03 +00:00
if err != nil {
2022-11-02 04:49:20 +00:00
snw.logger.Error("failed to check inbox",
2022-05-23 18:17:25 +00:00
zap.Error(err),
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-11-02 04:49:20 +00:00
return nil
2022-05-19 16:37:03 +00:00
}
2022-05-19 17:02:16 +00:00
found := false
for _, sthing := range sthings.Children {
if sthing.FullName() == account.LastMessageID {
found = true
}
}
if !found {
2022-11-02 04:49:20 +00:00
snw.logger.Debug("thing exists, but not on inbox, marking as deleted",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
zap.String("thing#id", account.LastMessageID),
)
2022-05-19 16:37:03 +00:00
break
2021-10-17 14:47:43 +00:00
}
2022-05-19 16:37:03 +00:00
2022-11-02 04:49:20 +00:00
snw.logger.Debug("thing exists, bailing early",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
zap.String("thing#id", account.LastMessageID),
)
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:47:43 +00:00
}
2021-10-17 14:17:41 +00:00
}
2022-11-02 04:49:20 +00:00
snw.logger.Info("thing got deleted, resetting",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
zap.String("thing#id", account.LastMessageID),
)
2021-10-17 14:17:41 +00:00
2021-10-17 14:47:43 +00:00
if kind != "t4" {
2022-11-02 04:49:20 +00:00
snw.logger.Debug("getting message inbox to find last good thing",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2021-10-17 15:48:41 +00:00
2022-10-27 00:46:17 +00:00
things, err = rac.MessageInbox(ctx)
2021-10-17 14:47:43 +00:00
if err != nil {
2022-11-02 04:49:20 +00:00
snw.logger.Error("failed to check inbox",
2022-05-23 18:17:25 +00:00
zap.Error(err),
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:47:43 +00:00
}
2021-10-17 14:17:41 +00:00
}
account.LastMessageID = ""
2021-10-17 15:48:41 +00:00
2022-11-02 04:49:20 +00:00
snw.logger.Debug("calculating last good thing",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2021-10-17 14:47:43 +00:00
for _, thing := range things.Children {
2021-10-17 15:27:52 +00:00
if thing.IsDeleted() {
2022-11-02 04:49:20 +00:00
snw.logger.Debug("thing got deleted, checking next",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
zap.String("thing#id", thing.FullName()),
)
2021-10-17 15:27:52 +00:00
continue
}
2021-10-17 15:48:41 +00:00
account.LastMessageID = thing.FullName()
break
2021-10-17 14:17:41 +00:00
}
2022-11-02 04:49:20 +00:00
snw.logger.Debug("updating last good thing",
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
zap.String("thing#id", account.LastMessageID),
)
2021-10-17 15:27:52 +00:00
2022-11-02 04:49:20 +00:00
if err := snw.accountRepo.Update(ctx, &account); err != nil {
snw.logger.Error("failed to update account's last message id",
2022-05-23 18:17:25 +00:00
zap.Error(err),
2022-11-02 05:15:25 +00:00
zap.String("account#reddit_account_id", id),
2022-05-23 18:17:25 +00:00
zap.String("account#username", account.NormalizedUsername()),
)
2022-11-02 04:49:20 +00:00
return err
2021-10-17 14:17:41 +00:00
}
2022-11-02 04:49:20 +00:00
return nil
2021-10-17 14:17:41 +00:00
}