Skip to content

Commit 19663d7

Browse files
committed
Merge remote-tracking branch 'origin/main' into cj/workspaces-last-used-at-timestamptz
2 parents cd580fb + 72dff7f commit 19663d7

27 files changed

+1398
-271
lines changed

cli/exp_scaletest.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,7 +857,7 @@ func (r *RootCmd) scaletestCreateWorkspaces() *clibase.Cmd {
857857
Flag: "use-host-login",
858858
Env: "CODER_SCALETEST_USE_HOST_LOGIN",
859859
Default: "false",
860-
Description: "Use the use logged in on the host machine, instead of creating users.",
860+
Description: "Use the user logged in on the host machine, instead of creating users.",
861861
Value: clibase.BoolOf(&useHostUser),
862862
},
863863
}

coderd/database/dbauthz/dbauthz.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,15 @@ func (q *querier) ActivityBumpWorkspace(ctx context.Context, arg uuid.UUID) erro
664664
return update(q.log, q.auth, fetch, q.db.ActivityBumpWorkspace)(ctx, arg)
665665
}
666666

667+
func (q *querier) AllUserIDs(ctx context.Context) ([]uuid.UUID, error) {
668+
// Although this technically only reads users, only system-related functions should be
669+
// allowed to call this.
670+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
671+
return nil, err
672+
}
673+
return q.db.AllUserIDs(ctx)
674+
}
675+
667676
func (q *querier) CleanTailnetCoordinators(ctx context.Context) error {
668677
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
669678
return err
@@ -1247,42 +1256,42 @@ func (q *querier) GetTemplateDAUs(ctx context.Context, arg database.GetTemplateD
12471256
return q.db.GetTemplateDAUs(ctx, arg)
12481257
}
12491258

1250-
func (q *querier) GetTemplateDailyInsights(ctx context.Context, arg database.GetTemplateDailyInsightsParams) ([]database.GetTemplateDailyInsightsRow, error) {
1259+
func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
12511260
for _, templateID := range arg.TemplateIDs {
12521261
template, err := q.db.GetTemplateByID(ctx, templateID)
12531262
if err != nil {
1254-
return nil, err
1263+
return database.GetTemplateInsightsRow{}, err
12551264
}
12561265

12571266
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
1258-
return nil, err
1267+
return database.GetTemplateInsightsRow{}, err
12591268
}
12601269
}
12611270
if len(arg.TemplateIDs) == 0 {
12621271
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil {
1263-
return nil, err
1272+
return database.GetTemplateInsightsRow{}, err
12641273
}
12651274
}
1266-
return q.db.GetTemplateDailyInsights(ctx, arg)
1275+
return q.db.GetTemplateInsights(ctx, arg)
12671276
}
12681277

1269-
func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
1278+
func (q *querier) GetTemplateInsightsByInterval(ctx context.Context, arg database.GetTemplateInsightsByIntervalParams) ([]database.GetTemplateInsightsByIntervalRow, error) {
12701279
for _, templateID := range arg.TemplateIDs {
12711280
template, err := q.db.GetTemplateByID(ctx, templateID)
12721281
if err != nil {
1273-
return database.GetTemplateInsightsRow{}, err
1282+
return nil, err
12741283
}
12751284

12761285
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
1277-
return database.GetTemplateInsightsRow{}, err
1286+
return nil, err
12781287
}
12791288
}
12801289
if len(arg.TemplateIDs) == 0 {
12811290
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil {
1282-
return database.GetTemplateInsightsRow{}, err
1291+
return nil, err
12831292
}
12841293
}
1285-
return q.db.GetTemplateInsights(ctx, arg)
1294+
return q.db.GetTemplateInsightsByInterval(ctx, arg)
12861295
}
12871296

12881297
func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database.GetTemplateParameterInsightsParams) ([]database.GetTemplateParameterInsightsRow, error) {

coderd/database/dbfake/dbfake.go

Lines changed: 92 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,16 @@ func (q *FakeQuerier) ActivityBumpWorkspace(ctx context.Context, workspaceID uui
812812
return sql.ErrNoRows
813813
}
814814

815+
func (q *FakeQuerier) AllUserIDs(_ context.Context) ([]uuid.UUID, error) {
816+
q.mutex.RLock()
817+
defer q.mutex.RUnlock()
818+
userIDs := make([]uuid.UUID, 0, len(q.users))
819+
for idx := range q.users {
820+
userIDs[idx] = q.users[idx].ID
821+
}
822+
return userIDs, nil
823+
}
824+
815825
func (*FakeQuerier) CleanTailnetCoordinators(_ context.Context) error {
816826
return ErrUnimplemented
817827
}
@@ -2340,7 +2350,76 @@ func (q *FakeQuerier) GetTemplateDAUs(_ context.Context, arg database.GetTemplat
23402350
return rs, nil
23412351
}
23422352

2343-
func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database.GetTemplateDailyInsightsParams) ([]database.GetTemplateDailyInsightsRow, error) {
2353+
func (q *FakeQuerier) GetTemplateInsights(_ context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
2354+
err := validateDatabaseType(arg)
2355+
if err != nil {
2356+
return database.GetTemplateInsightsRow{}, err
2357+
}
2358+
2359+
templateIDSet := make(map[uuid.UUID]struct{})
2360+
appUsageIntervalsByUser := make(map[uuid.UUID]map[time.Time]*database.GetTemplateInsightsRow)
2361+
for _, s := range q.workspaceAgentStats {
2362+
if s.CreatedAt.Before(arg.StartTime) || s.CreatedAt.Equal(arg.EndTime) || s.CreatedAt.After(arg.EndTime) {
2363+
continue
2364+
}
2365+
if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) {
2366+
continue
2367+
}
2368+
if s.ConnectionCount == 0 {
2369+
continue
2370+
}
2371+
2372+
templateIDSet[s.TemplateID] = struct{}{}
2373+
if appUsageIntervalsByUser[s.UserID] == nil {
2374+
appUsageIntervalsByUser[s.UserID] = make(map[time.Time]*database.GetTemplateInsightsRow)
2375+
}
2376+
t := s.CreatedAt.Truncate(time.Minute)
2377+
if _, ok := appUsageIntervalsByUser[s.UserID][t]; !ok {
2378+
appUsageIntervalsByUser[s.UserID][t] = &database.GetTemplateInsightsRow{}
2379+
}
2380+
2381+
if s.SessionCountJetBrains > 0 {
2382+
appUsageIntervalsByUser[s.UserID][t].UsageJetbrainsSeconds = 60
2383+
}
2384+
if s.SessionCountVSCode > 0 {
2385+
appUsageIntervalsByUser[s.UserID][t].UsageVscodeSeconds = 60
2386+
}
2387+
if s.SessionCountReconnectingPTY > 0 {
2388+
appUsageIntervalsByUser[s.UserID][t].UsageReconnectingPtySeconds = 60
2389+
}
2390+
if s.SessionCountSSH > 0 {
2391+
appUsageIntervalsByUser[s.UserID][t].UsageSshSeconds = 60
2392+
}
2393+
}
2394+
2395+
templateIDs := make([]uuid.UUID, 0, len(templateIDSet))
2396+
for templateID := range templateIDSet {
2397+
templateIDs = append(templateIDs, templateID)
2398+
}
2399+
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
2400+
return slice.Ascending(a.String(), b.String())
2401+
})
2402+
activeUserIDs := make([]uuid.UUID, 0, len(appUsageIntervalsByUser))
2403+
for userID := range appUsageIntervalsByUser {
2404+
activeUserIDs = append(activeUserIDs, userID)
2405+
}
2406+
2407+
result := database.GetTemplateInsightsRow{
2408+
TemplateIDs: templateIDs,
2409+
ActiveUserIDs: activeUserIDs,
2410+
}
2411+
for _, intervals := range appUsageIntervalsByUser {
2412+
for _, interval := range intervals {
2413+
result.UsageJetbrainsSeconds += interval.UsageJetbrainsSeconds
2414+
result.UsageVscodeSeconds += interval.UsageVscodeSeconds
2415+
result.UsageReconnectingPtySeconds += interval.UsageReconnectingPtySeconds
2416+
result.UsageSshSeconds += interval.UsageSshSeconds
2417+
}
2418+
}
2419+
return result, nil
2420+
}
2421+
2422+
func (q *FakeQuerier) GetTemplateInsightsByInterval(ctx context.Context, arg database.GetTemplateInsightsByIntervalParams) ([]database.GetTemplateInsightsByIntervalRow, error) {
23442423
err := validateDatabaseType(arg)
23452424
if err != nil {
23462425
return nil, err
@@ -2349,17 +2428,18 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23492428
q.mutex.RLock()
23502429
defer q.mutex.RUnlock()
23512430

2352-
type dailyStat struct {
2431+
type statByInterval struct {
23532432
startTime, endTime time.Time
23542433
userSet map[uuid.UUID]struct{}
23552434
templateIDSet map[uuid.UUID]struct{}
23562435
}
2357-
dailyStats := []dailyStat{{arg.StartTime, arg.StartTime.AddDate(0, 0, 1), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
2358-
for dailyStats[len(dailyStats)-1].endTime.Before(arg.EndTime) {
2359-
dailyStats = append(dailyStats, dailyStat{dailyStats[len(dailyStats)-1].endTime, dailyStats[len(dailyStats)-1].endTime.AddDate(0, 0, 1), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
2436+
2437+
statsByInterval := []statByInterval{{arg.StartTime, arg.StartTime.AddDate(0, 0, int(arg.IntervalDays)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
2438+
for statsByInterval[len(statsByInterval)-1].endTime.Before(arg.EndTime) {
2439+
statsByInterval = append(statsByInterval, statByInterval{statsByInterval[len(statsByInterval)-1].endTime, statsByInterval[len(statsByInterval)-1].endTime.AddDate(0, 0, int(arg.IntervalDays)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
23602440
}
2361-
if dailyStats[len(dailyStats)-1].endTime.After(arg.EndTime) {
2362-
dailyStats[len(dailyStats)-1].endTime = arg.EndTime
2441+
if statsByInterval[len(statsByInterval)-1].endTime.After(arg.EndTime) {
2442+
statsByInterval[len(statsByInterval)-1].endTime = arg.EndTime
23632443
}
23642444

23652445
for _, s := range q.workspaceAgentStats {
@@ -2373,7 +2453,7 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23732453
continue
23742454
}
23752455

2376-
for _, ds := range dailyStats {
2456+
for _, ds := range statsByInterval {
23772457
if s.CreatedAt.Before(ds.startTime) || s.CreatedAt.Equal(ds.endTime) || s.CreatedAt.After(ds.endTime) {
23782458
continue
23792459
}
@@ -2392,7 +2472,7 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23922472
continue
23932473
}
23942474

2395-
for _, ds := range dailyStats {
2475+
for _, ds := range statsByInterval {
23962476
// (was.session_started_at >= ts.from_ AND was.session_started_at < ts.to_)
23972477
// OR (was.session_ended_at > ts.from_ AND was.session_ended_at < ts.to_)
23982478
// OR (was.session_started_at < ts.from_ AND was.session_ended_at >= ts.to_)
@@ -2407,16 +2487,16 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
24072487
}
24082488
}
24092489

2410-
var result []database.GetTemplateDailyInsightsRow
2411-
for _, ds := range dailyStats {
2490+
var result []database.GetTemplateInsightsByIntervalRow
2491+
for _, ds := range statsByInterval {
24122492
templateIDs := make([]uuid.UUID, 0, len(ds.templateIDSet))
24132493
for templateID := range ds.templateIDSet {
24142494
templateIDs = append(templateIDs, templateID)
24152495
}
24162496
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
24172497
return slice.Ascending(a.String(), b.String())
24182498
})
2419-
result = append(result, database.GetTemplateDailyInsightsRow{
2499+
result = append(result, database.GetTemplateInsightsByIntervalRow{
24202500
StartTime: ds.startTime,
24212501
EndTime: ds.endTime,
24222502
TemplateIDs: templateIDs,
@@ -2426,75 +2506,6 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
24262506
return result, nil
24272507
}
24282508

2429-
func (q *FakeQuerier) GetTemplateInsights(_ context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
2430-
err := validateDatabaseType(arg)
2431-
if err != nil {
2432-
return database.GetTemplateInsightsRow{}, err
2433-
}
2434-
2435-
templateIDSet := make(map[uuid.UUID]struct{})
2436-
appUsageIntervalsByUser := make(map[uuid.UUID]map[time.Time]*database.GetTemplateInsightsRow)
2437-
for _, s := range q.workspaceAgentStats {
2438-
if s.CreatedAt.Before(arg.StartTime) || s.CreatedAt.Equal(arg.EndTime) || s.CreatedAt.After(arg.EndTime) {
2439-
continue
2440-
}
2441-
if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) {
2442-
continue
2443-
}
2444-
if s.ConnectionCount == 0 {
2445-
continue
2446-
}
2447-
2448-
templateIDSet[s.TemplateID] = struct{}{}
2449-
if appUsageIntervalsByUser[s.UserID] == nil {
2450-
appUsageIntervalsByUser[s.UserID] = make(map[time.Time]*database.GetTemplateInsightsRow)
2451-
}
2452-
t := s.CreatedAt.Truncate(time.Minute)
2453-
if _, ok := appUsageIntervalsByUser[s.UserID][t]; !ok {
2454-
appUsageIntervalsByUser[s.UserID][t] = &database.GetTemplateInsightsRow{}
2455-
}
2456-
2457-
if s.SessionCountJetBrains > 0 {
2458-
appUsageIntervalsByUser[s.UserID][t].UsageJetbrainsSeconds = 60
2459-
}
2460-
if s.SessionCountVSCode > 0 {
2461-
appUsageIntervalsByUser[s.UserID][t].UsageVscodeSeconds = 60
2462-
}
2463-
if s.SessionCountReconnectingPTY > 0 {
2464-
appUsageIntervalsByUser[s.UserID][t].UsageReconnectingPtySeconds = 60
2465-
}
2466-
if s.SessionCountSSH > 0 {
2467-
appUsageIntervalsByUser[s.UserID][t].UsageSshSeconds = 60
2468-
}
2469-
}
2470-
2471-
templateIDs := make([]uuid.UUID, 0, len(templateIDSet))
2472-
for templateID := range templateIDSet {
2473-
templateIDs = append(templateIDs, templateID)
2474-
}
2475-
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
2476-
return slice.Ascending(a.String(), b.String())
2477-
})
2478-
activeUserIDs := make([]uuid.UUID, 0, len(appUsageIntervalsByUser))
2479-
for userID := range appUsageIntervalsByUser {
2480-
activeUserIDs = append(activeUserIDs, userID)
2481-
}
2482-
2483-
result := database.GetTemplateInsightsRow{
2484-
TemplateIDs: templateIDs,
2485-
ActiveUserIDs: activeUserIDs,
2486-
}
2487-
for _, intervals := range appUsageIntervalsByUser {
2488-
for _, interval := range intervals {
2489-
result.UsageJetbrainsSeconds += interval.UsageJetbrainsSeconds
2490-
result.UsageVscodeSeconds += interval.UsageVscodeSeconds
2491-
result.UsageReconnectingPtySeconds += interval.UsageReconnectingPtySeconds
2492-
result.UsageSshSeconds += interval.UsageSshSeconds
2493-
}
2494-
}
2495-
return result, nil
2496-
}
2497-
24982509
func (q *FakeQuerier) GetTemplateParameterInsights(ctx context.Context, arg database.GetTemplateParameterInsightsParams) ([]database.GetTemplateParameterInsightsRow, error) {
24992510
err := validateDatabaseType(arg)
25002511
if err != nil {

coderd/database/dbgen/dbgen.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func User(t testing.TB, db database.Store, orig database.User) database.User {
227227

228228
user, err = db.UpdateUserStatus(genCtx, database.UpdateUserStatusParams{
229229
ID: user.ID,
230-
Status: database.UserStatusActive,
230+
Status: takeFirst(orig.Status, database.UserStatusActive),
231231
UpdatedAt: dbtime.Now(),
232232
})
233233
require.NoError(t, err, "insert user")
@@ -240,6 +240,14 @@ func User(t testing.TB, db database.Store, orig database.User) database.User {
240240
})
241241
require.NoError(t, err, "user last seen")
242242
}
243+
244+
if orig.Deleted {
245+
err = db.UpdateUserDeletedByID(genCtx, database.UpdateUserDeletedByIDParams{
246+
ID: user.ID,
247+
Deleted: orig.Deleted,
248+
})
249+
require.NoError(t, err, "set user as deleted")
250+
}
243251
return user
244252
}
245253

coderd/database/dbmetrics/dbmetrics.go

Lines changed: 13 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)