MCPcopy Index your code
hub / github.com/coder/coder / reportFailedWorkspaceBuilds

Function reportFailedWorkspaceBuilds

coderd/notifications/reports/generator.go:110–226  ·  view source on GitHub ↗
(ctx context.Context, logger slog.Logger, db database.Store, enqueuer notifications.Enqueuer, clk quartz.Clock)

Source from the content-addressed store, hash-verified

108}
109
110func reportFailedWorkspaceBuilds(ctx context.Context, logger slog.Logger, db database.Store, enqueuer notifications.Enqueuer, clk quartz.Clock) error {
111 now := clk.Now()
112 since := now.Add(-failedWorkspaceBuildsReportFrequency)
113
114 // Firstly, check if this is the first run of the job ever
115 reportLog, err := db.GetNotificationReportGeneratorLogByTemplate(ctx, notifications.TemplateWorkspaceBuildsFailedReport)
116 if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
117 return xerrors.Errorf("unable to read report generator log: %w", err)
118 }
119 if xerrors.Is(err, sql.ErrNoRows) {
120 // First run? Check-in the job, and get back after one week.
121 logger.Info(ctx, "report generator is executing the job for the first time", slog.F("notification_template_id", notifications.TemplateWorkspaceBuildsFailedReport))
122
123 err = db.UpsertNotificationReportGeneratorLog(ctx, database.UpsertNotificationReportGeneratorLogParams{
124 NotificationTemplateID: notifications.TemplateWorkspaceBuildsFailedReport,
125 LastGeneratedAt: dbtime.Time(now).UTC(),
126 })
127 if err != nil {
128 return xerrors.Errorf("unable to update report generator logs (first time execution): %w", err)
129 }
130 return nil
131 }
132
133 // Secondly, check if the job has not been running recently
134 if !reportLog.LastGeneratedAt.IsZero() && reportLog.LastGeneratedAt.Add(failedWorkspaceBuildsReportFrequency).After(now) {
135 return nil // reports sent recently, no need to send them now
136 }
137
138 // Thirdly, fetch workspace build stats by templates
139 templateStatsRows, err := db.GetWorkspaceBuildStatsByTemplates(ctx, dbtime.Time(since).UTC())
140 if err != nil {
141 return xerrors.Errorf("unable to fetch failed workspace builds: %w", err)
142 }
143
144 reports := make(map[uuid.UUID][]adminReport)
145
146 for _, stats := range templateStatsRows {
147 select {
148 case <-ctx.Done():
149 logger.Debug(ctx, "context is canceled, quitting", slog.Error(ctx.Err()))
150 break
151 default:
152 }
153
154 if stats.FailedBuilds == 0 {
155 logger.Info(ctx, "no failed workspace builds found for template", slog.F("template_id", stats.TemplateID), slog.Error(err))
156 continue
157 }
158
159 // Fetch template admins with org access to the templates
160 templateAdmins, err := findTemplateAdmins(ctx, db, stats)
161 if err != nil {
162 logger.Error(ctx, "unable to find template admins for template", slog.F("template_id", stats.TemplateID), slog.Error(err))
163 continue
164 }
165
166 // Fetch failed builds by the template
167 failedBuilds, err := db.GetFailedWorkspaceBuildsByTemplateID(ctx, database.GetFailedWorkspaceBuildsByTemplateIDParams{

Callers 2

NewReportGeneratorFunction · 0.85

Calls 15

TimeFunction · 0.92
UniqueFunction · 0.92
ErrMethod · 0.80
findTemplateAdminsFunction · 0.70
AddMethod · 0.65
EnqueueWithDataMethod · 0.65
IsMethod · 0.45

Tested by 1