Skip to content

Commit d4cd43d

Browse files
committed
Add code to automatically do heartbeat checks
1 parent cc3d307 commit d4cd43d

3 files changed

Lines changed: 51 additions & 46 deletions

File tree

api/pkg/di/container.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -268,26 +268,10 @@ func (container *Container) DB() (db *gorm.DB) {
268268
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.Message{})))
269269
}
270270

271-
if err = db.AutoMigrate(&repositories.GormEvent{}); err != nil {
272-
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &repositories.GormEvent{})))
273-
}
274-
275-
if err = db.AutoMigrate(&entities.EventListenerLog{}); err != nil {
276-
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.EventListenerLog{})))
277-
}
278-
279271
if err = db.AutoMigrate(&entities.MessageThread{}); err != nil {
280272
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.MessageThread{})))
281273
}
282274

283-
if err = db.AutoMigrate(&entities.Heartbeat{}); err != nil {
284-
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.Heartbeat{})))
285-
}
286-
287-
if err = db.AutoMigrate(&entities.HeartbeatMonitor{}); err != nil {
288-
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.HeartbeatMonitor{})))
289-
}
290-
291275
if err = db.AutoMigrate(&entities.User{}); err != nil {
292276
container.logger.Fatal(stacktrace.Propagate(err, fmt.Sprintf("cannot migrate %T", &entities.User{})))
293277
}
@@ -693,7 +677,7 @@ func (container *Container) HeartbeatMonitorRepository() (repository repositorie
693677
return repositories.NewGormHeartbeatMonitorRepository(
694678
container.Logger(),
695679
container.Tracer(),
696-
container.DB(),
680+
container.YugaByteDB(),
697681
)
698682
}
699683

api/pkg/entities/heartbeat_monitor.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ type HeartbeatMonitor struct {
1616
CreatedAt time.Time `json:"created_at" example:"2022-06-05T14:26:02.302718+03:00"`
1717
UpdatedAt time.Time `json:"updated_at" example:"2022-06-05T14:26:10.303278+03:00"`
1818
}
19+
20+
// RequiresCheck returns true if the heartbeat monitor requires a check
21+
func (h *HeartbeatMonitor) RequiresCheck() bool {
22+
return h.UpdatedAt.Add(2 * time.Hour).Before(time.Now())
23+
}

api/pkg/services/heartbeat_service.go

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -108,51 +108,67 @@ type HeartbeatMonitorStoreParams struct {
108108

109109
// StoreMonitor a new entities.HeartbeatMonitor
110110
func (service *HeartbeatService) StoreMonitor(ctx context.Context, params *HeartbeatMonitorStoreParams) (*entities.HeartbeatMonitor, error) {
111-
ctx, span := service.tracer.Start(ctx)
111+
ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
112112
defer span.End()
113113

114-
ctxLogger := service.tracer.CtxLogger(service.logger, span)
115-
116-
exists, err := service.monitorRepository.Exists(ctx, params.UserID, params.Owner)
114+
monitor, scheduleCheck, err := service.phoneMonitor(ctx, params)
117115
if err != nil {
118-
msg := fmt.Sprintf("cannot check if monitor exists with userID [%s] and owner [%s]", params.UserID, params.Owner)
116+
msg := fmt.Sprintf("cannot create monitor for with userID [%s] and owner [%s]", params.UserID, params.Owner)
119117
return nil, service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
120118
}
121119

122-
if exists {
123-
ctxLogger.Info(fmt.Sprintf("heartbeat monitor exists for owner [%s] and user [%s]", params.Owner, params.UserID))
124-
return nil, nil
125-
}
126-
127-
heartbeatMonitor := &entities.HeartbeatMonitor{
128-
ID: uuid.New(),
129-
PhoneID: params.PhoneID,
130-
UserID: params.UserID,
131-
Owner: params.Owner,
132-
CreatedAt: time.Now().UTC(),
133-
UpdatedAt: time.Now().UTC(),
134-
}
135-
136-
if err = service.monitorRepository.Store(ctx, heartbeatMonitor); err != nil {
137-
msg := fmt.Sprintf("cannot save heartbeat monitor for owner [%s] and user [%s]", heartbeatMonitor.Owner, heartbeatMonitor.UserID)
138-
return nil, service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
120+
if !scheduleCheck {
121+
ctxLogger.Info(fmt.Sprintf("heartbeat monitor [%s] for owner [%s] does not need scheduling because it was updated at [%s]", monitor.ID, monitor.Owner, monitor.UpdatedAt))
122+
return monitor, nil
139123
}
140124

141-
ctxLogger.Info(fmt.Sprintf("heartbeat monitor saved with id [%s] for owner [%s] and user [%s]", heartbeatMonitor.ID, heartbeatMonitor.Owner, heartbeatMonitor.UserID))
125+
ctxLogger.Info(fmt.Sprintf("scheduling heartbeat monitor [%s] for owner [%s] and user [%s]", monitor.ID, monitor.Owner, monitor.UserID))
142126

143127
monitorParams := &HeartbeatMonitorParams{
144-
Owner: heartbeatMonitor.Owner,
145-
PhoneID: heartbeatMonitor.PhoneID,
146-
UserID: heartbeatMonitor.UserID,
147-
MonitorID: heartbeatMonitor.ID,
128+
Owner: monitor.Owner,
129+
PhoneID: monitor.PhoneID,
130+
UserID: monitor.UserID,
131+
MonitorID: monitor.ID,
148132
Source: params.Source,
149133
}
150134
if err = service.scheduleHeartbeatCheck(ctx, time.Now().UTC(), monitorParams); err != nil {
151-
msg := fmt.Sprintf("cannot schedule healthcheck for monitor with owner [%s] and userID [%s]", params.Owner, params.UserID)
135+
msg := fmt.Sprintf("cannot schedule healthcheck for monitor [%s] with owner [%s] and userID [%s]", monitor.ID, params.Owner, params.UserID)
152136
return nil, service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
153137
}
154138

155-
return heartbeatMonitor, nil
139+
return monitor, nil
140+
}
141+
142+
func (service *HeartbeatService) phoneMonitor(ctx context.Context, params *HeartbeatMonitorStoreParams) (*entities.HeartbeatMonitor, bool, error) {
143+
ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
144+
defer span.End()
145+
146+
monitor, err := service.monitorRepository.Load(ctx, params.UserID, params.Owner)
147+
if stacktrace.GetCode(err) == repositories.ErrCodeNotFound {
148+
monitor = &entities.HeartbeatMonitor{
149+
ID: uuid.New(),
150+
PhoneID: params.PhoneID,
151+
UserID: params.UserID,
152+
Owner: params.Owner,
153+
CreatedAt: time.Now().UTC(),
154+
UpdatedAt: time.Now().UTC(),
155+
}
156+
157+
if err = service.monitorRepository.Store(ctx, monitor); err != nil {
158+
msg := fmt.Sprintf("cannot save heartbeat monitor for owner [%s] and user [%s]", monitor.Owner, monitor.UserID)
159+
return nil, false, service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
160+
}
161+
162+
ctxLogger.Info(fmt.Sprintf("heartbeat monitor saved with id [%s] for owner [%s] and user [%s]", monitor.ID, monitor.Owner, monitor.UserID))
163+
return monitor, true, nil
164+
}
165+
166+
if err != nil {
167+
msg := fmt.Sprintf("cannot check if monitor exists with userID [%s] and owner [%s]", params.UserID, params.Owner)
168+
return nil, false, service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
169+
}
170+
171+
return monitor, monitor.RequiresCheck(), nil
156172
}
157173

158174
// DeleteMonitor an entities.HeartbeatMonitor

0 commit comments

Comments
 (0)