fix: use unique workspace owners over unique users (#11044)

This commit is contained in:
Garrett Delfosse
2023-12-07 10:53:15 -05:00
committed by GitHub
parent 091fdd6761
commit 8aea6040c8
10 changed files with 212 additions and 2 deletions
+30
View File
@@ -52,6 +52,7 @@ type Cache struct {
deploymentDAUResponses atomic.Pointer[map[int]codersdk.DAUsResponse]
templateDAUResponses atomic.Pointer[map[int]map[uuid.UUID]codersdk.DAUsResponse]
templateUniqueUsers atomic.Pointer[map[uuid.UUID]int]
templateWorkspaceOwners atomic.Pointer[map[uuid.UUID]int]
templateAverageBuildTime atomic.Pointer[map[uuid.UUID]database.GetTemplateAverageBuildTimeRow]
deploymentStatsResponse atomic.Pointer[codersdk.DeploymentStats]
@@ -206,6 +207,7 @@ func (c *Cache) refreshTemplateDAUs(ctx context.Context) error {
var (
templateDAUs = make(map[int]map[uuid.UUID]codersdk.DAUsResponse, len(templates))
templateUniqueUsers = make(map[uuid.UUID]int)
templateWorkspaceOwners = make(map[uuid.UUID]int)
templateAverageBuildTimes = make(map[uuid.UUID]database.GetTemplateAverageBuildTimeRow)
)
@@ -214,7 +216,9 @@ func (c *Cache) refreshTemplateDAUs(ctx context.Context) error {
return xerrors.Errorf("deployment daus: %w", err)
}
ids := make([]uuid.UUID, 0, len(templates))
for _, template := range templates {
ids = append(ids, template.ID)
for _, tzOffset := range templateTimezoneOffsets {
rows, err := c.database.GetTemplateDAUs(ctx, database.GetTemplateDAUsParams{
TemplateID: template.ID,
@@ -249,6 +253,17 @@ func (c *Cache) refreshTemplateDAUs(ctx context.Context) error {
}
templateAverageBuildTimes[template.ID] = templateAvgBuildTime
}
owners, err := c.database.GetWorkspaceUniqueOwnerCountByTemplateIDs(ctx, ids)
if err != nil {
return xerrors.Errorf("get workspace unique owner count by template ids: %w", err)
}
for _, owner := range owners {
templateWorkspaceOwners[owner.TemplateID] = int(owner.UniqueOwnersSum)
}
c.templateWorkspaceOwners.Store(&templateWorkspaceOwners)
c.templateDAUResponses.Store(&templateDAUs)
c.templateUniqueUsers.Store(&templateUniqueUsers)
c.templateAverageBuildTime.Store(&templateAverageBuildTimes)
@@ -469,6 +484,21 @@ func (c *Cache) TemplateBuildTimeStats(id uuid.UUID) codersdk.TemplateBuildTimeS
}
}
func (c *Cache) TemplateWorkspaceOwners(id uuid.UUID) (int, bool) {
m := c.templateWorkspaceOwners.Load()
if m == nil {
// Data loading.
return -1, false
}
resp, ok := (*m)[id]
if !ok {
// Probably no data.
return -1, false
}
return resp, true
}
func (c *Cache) DeploymentStats() (codersdk.DeploymentStats, bool) {
deploymentStats := c.deploymentStatsResponse.Load()
if deploymentStats == nil {
+68
View File
@@ -254,6 +254,74 @@ func TestCache_TemplateUsers(t *testing.T) {
}
}
func TestCache_TemplateWorkspaceOwners(t *testing.T) {
t.Parallel()
var ()
var (
db = dbmem.New()
cache = metricscache.New(db, slogtest.Make(t, nil), metricscache.Intervals{
TemplateDAUs: testutil.IntervalFast,
})
)
defer cache.Close()
user1 := dbgen.User(t, db, database.User{})
user2 := dbgen.User(t, db, database.User{})
template := dbgen.Template(t, db, database.Template{
Provisioner: database.ProvisionerTypeEcho,
})
require.Eventuallyf(t, func() bool {
count, ok := cache.TemplateWorkspaceOwners(template.ID)
return ok && count == 0
}, testutil.WaitShort, testutil.IntervalMedium,
"TemplateWorkspaceOwners never populated 0 owners",
)
dbgen.Workspace(t, db, database.Workspace{
TemplateID: template.ID,
OwnerID: user1.ID,
})
require.Eventuallyf(t, func() bool {
count, _ := cache.TemplateWorkspaceOwners(template.ID)
return count == 1
}, testutil.WaitShort, testutil.IntervalMedium,
"TemplateWorkspaceOwners never populated 1 owner",
)
workspace2 := dbgen.Workspace(t, db, database.Workspace{
TemplateID: template.ID,
OwnerID: user2.ID,
})
require.Eventuallyf(t, func() bool {
count, _ := cache.TemplateWorkspaceOwners(template.ID)
return count == 2
}, testutil.WaitShort, testutil.IntervalMedium,
"TemplateWorkspaceOwners never populated 2 owners",
)
// 3rd workspace should not be counted since we have the same owner as workspace2.
dbgen.Workspace(t, db, database.Workspace{
TemplateID: template.ID,
OwnerID: user1.ID,
})
db.UpdateWorkspaceDeletedByID(context.Background(), database.UpdateWorkspaceDeletedByIDParams{
ID: workspace2.ID,
Deleted: true,
})
require.Eventuallyf(t, func() bool {
count, _ := cache.TemplateWorkspaceOwners(template.ID)
return count == 1
}, testutil.WaitShort, testutil.IntervalMedium,
"TemplateWorkspaceOwners never populated 1 owner after delete",
)
}
func clockTime(t time.Time, hour, minute, sec int) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), hour, minute, sec, t.Nanosecond(), t.Location())
}