Skip to content

Commit c461c4e

Browse files
committed
feat(state): add current check state by service
1 parent b404701 commit c461c4e

File tree

5 files changed

+140
-11
lines changed

5 files changed

+140
-11
lines changed

internal/app/app.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ type App struct {
2727
logger logger.Logger
2828
}
2929

30-
func NewApp(cfg *config.Config, logger logger.Logger, checkSvc checksvc.CheckHandlerService) *App {
30+
func NewApp(
31+
cfg *config.Config,
32+
logger logger.Logger,
33+
checkSvc checksvc.CheckHandlerService,
34+
) *App {
3135
return &App{
3236
cfg: cfg,
3337
checkHandlerSvc: checkSvc,

internal/repository/check/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
type CheckStateRepository interface {
1010
GetCheckState(context.Context, string, string) (*model.CheckState, error)
1111
UpsertCheckState(context.Context, *model.CheckState) error
12+
ListCheckStatesByService(context.Context, string) ([]model.CheckState, error)
1213
}
1314

1415
type CheckExecutionRepository interface {

internal/repository/check/state.go

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,25 @@ ON CONFLICT (check_id, service_id) DO UPDATE SET
142142
`
143143

144144
var (
145-
details []byte
146-
errorKind *string
147-
errorMessage *string
145+
rawDetails []byte
146+
rawErrorKind *string
147+
rawErrorMessage *string
148148
)
149149

150150
if state.LastDetails != nil {
151151
data, err := json.Marshal(state.LastDetails)
152152
if err != nil {
153153
return err
154154
}
155-
details = data
155+
rawDetails = data
156156
}
157157

158158
if state.LastErrorKind != e.ErrNone {
159-
value := string(state.LastErrorKind)
160-
errorKind = &value
159+
rawErrorKind = new(string(state.LastErrorKind))
161160
}
162161

163162
if state.LastErrorMessage != "" {
164-
errorMessage = &state.LastErrorMessage
163+
rawErrorMessage = &state.LastErrorMessage
165164
}
166165

167166
_, err := s.db.Exec(ctx, query,
@@ -171,10 +170,10 @@ ON CONFLICT (check_id, service_id) DO UPDATE SET
171170
state.Status,
172171
state.LastExecutionID,
173172
state.LastStatus,
174-
errorKind,
175-
errorMessage,
173+
rawErrorKind,
174+
rawErrorMessage,
176175
state.LastDuration.Microseconds(),
177-
details,
176+
rawDetails,
178177
state.LastSuccessAt,
179178
state.LastFailureAt,
180179
state.ConsecutiveSuccesses,
@@ -185,6 +184,92 @@ ON CONFLICT (check_id, service_id) DO UPDATE SET
185184
return err
186185
}
187186

187+
func (s *StateCheck) ListCheckStatesByService(
188+
ctx context.Context,
189+
serviceID string,
190+
) ([]model.CheckState, error) {
191+
query := `
192+
SELECT
193+
check_id,
194+
check_type,
195+
status,
196+
last_execution_id,
197+
last_status,
198+
last_error_kind,
199+
last_error_message,
200+
last_duration,
201+
last_details,
202+
last_success_at,
203+
last_failure_at,
204+
consecutive_successes,
205+
consecutive_failures,
206+
updated_at
207+
FROM pulse.check_states
208+
WHERE service_id = $1
209+
ORDER BY check_id
210+
`
211+
212+
var result []model.CheckState
213+
rows, err := s.db.Query(ctx, query, serviceID)
214+
if err != nil {
215+
return nil, err
216+
}
217+
defer rows.Close()
218+
219+
for rows.Next() {
220+
var (
221+
rawDetails []byte
222+
rawErrorKind *string
223+
rawErrorMessage *string
224+
rawDurationUs int64
225+
)
226+
state := model.CheckState{ServiceID: serviceID}
227+
err = rows.Scan(
228+
&state.CheckID,
229+
&state.CheckType,
230+
&state.Status,
231+
&state.LastExecutionID,
232+
&state.LastStatus,
233+
&rawErrorKind,
234+
&rawErrorMessage,
235+
&rawDurationUs,
236+
&rawDetails,
237+
&state.LastSuccessAt,
238+
&state.LastFailureAt,
239+
&state.ConsecutiveSuccesses,
240+
&state.ConsecutiveFailures,
241+
&state.UpdatedAt,
242+
)
243+
if err != nil {
244+
return nil, err
245+
}
246+
247+
if rawErrorKind != nil {
248+
state.LastErrorKind = e.ErrorKind(*rawErrorKind)
249+
}
250+
251+
if rawErrorMessage != nil {
252+
state.LastErrorMessage = *rawErrorMessage
253+
}
254+
255+
if rawDetails != nil {
256+
if err = json.Unmarshal(rawDetails, &state.LastDetails); err != nil {
257+
return nil, err
258+
}
259+
}
260+
261+
state.LastDuration = time.Duration(rawDurationUs) * time.Microsecond
262+
263+
result = append(result, state)
264+
}
265+
266+
if err = rows.Err(); err != nil {
267+
return nil, err
268+
}
269+
270+
return result, nil
271+
}
272+
188273
func NewStateRepository(db repository.QueryExecutor) *StateCheck {
189274
return &StateCheck{db}
190275
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package state
2+
3+
import (
4+
"context"
5+
6+
"github.com/pixel365/pulse/internal/model"
7+
)
8+
9+
type StateService interface {
10+
GetStatesByService(context.Context, string) ([]model.CheckState, error)
11+
}

internal/services/state/state.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package state
2+
3+
import (
4+
"context"
5+
6+
"github.com/pixel365/pulse/internal/model"
7+
"github.com/pixel365/pulse/internal/repository"
8+
"github.com/pixel365/pulse/internal/repository/check"
9+
)
10+
11+
var _ StateService = (*State)(nil)
12+
13+
type State struct {
14+
repo check.CheckStateRepository
15+
}
16+
17+
func (s *State) GetStatesByService(
18+
ctx context.Context,
19+
serviceID string,
20+
) ([]model.CheckState, error) {
21+
return s.repo.ListCheckStatesByService(ctx, serviceID)
22+
}
23+
24+
func NewStateService(db repository.QueryExecutor) *State {
25+
return &State{
26+
repo: check.NewStateRepository(db),
27+
}
28+
}

0 commit comments

Comments
 (0)