fix: Only update workspace LastUsed when the connection payload has changed (#4115)

This was causing every workspace to update last used to time.Now() when
coderd was restarted!
This commit is contained in:
Kyle Carberry
2022-09-19 14:11:18 -05:00
committed by GitHub
parent 153e96f574
commit 72d6731924
5 changed files with 63 additions and 1 deletions

View File

@ -159,6 +159,33 @@ func (q *fakeQuerier) InsertAgentStat(_ context.Context, p database.InsertAgentS
return stat, nil
}
func (q *fakeQuerier) GetLatestAgentStat(_ context.Context, agentID uuid.UUID) (database.AgentStat, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()
found := false
latest := database.AgentStat{}
for _, agentStat := range q.agentStats {
if agentStat.AgentID != agentID {
continue
}
if !found {
latest = agentStat
found = true
continue
}
if agentStat.CreatedAt.After(latest.CreatedAt) {
latest = agentStat
found = true
continue
}
}
if !found {
return database.AgentStat{}, sql.ErrNoRows
}
return latest, nil
}
func (q *fakeQuerier) GetTemplateDAUs(_ context.Context, templateID uuid.UUID) ([]database.GetTemplateDAUsRow, error) {
q.mutex.Lock()
defer q.mutex.Unlock()

View File

@ -37,6 +37,7 @@ type querier interface {
GetDeploymentID(ctx context.Context) (string, error)
GetFileByHash(ctx context.Context, hash string) (File, error)
GetGitSSHKey(ctx context.Context, userID uuid.UUID) (GitSSHKey, error)
GetLatestAgentStat(ctx context.Context, agentID uuid.UUID) (AgentStat, error)
GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (WorkspaceBuild, error)
GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceBuild, error)
GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceBuild, error)

View File

@ -24,6 +24,25 @@ func (q *sqlQuerier) DeleteOldAgentStats(ctx context.Context) error {
return err
}
const getLatestAgentStat = `-- name: GetLatestAgentStat :one
SELECT id, created_at, user_id, agent_id, workspace_id, template_id, payload FROM agent_stats WHERE agent_id = $1 ORDER BY created_at DESC LIMIT 1
`
func (q *sqlQuerier) GetLatestAgentStat(ctx context.Context, agentID uuid.UUID) (AgentStat, error) {
row := q.db.QueryRowContext(ctx, getLatestAgentStat, agentID)
var i AgentStat
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UserID,
&i.AgentID,
&i.WorkspaceID,
&i.TemplateID,
&i.Payload,
)
return i, err
}
const getTemplateDAUs = `-- name: GetTemplateDAUs :many
select
(created_at at TIME ZONE 'UTC')::date as date,

View File

@ -12,6 +12,9 @@ INSERT INTO
VALUES
($1, $2, $3, $4, $5, $6, $7) RETURNING *;
-- name: GetLatestAgentStat :one
SELECT * FROM agent_stats WHERE agent_id = $1 ORDER BY created_at DESC LIMIT 1;
-- name: GetTemplateDAUs :many
select
(created_at at TIME ZONE 'UTC')::date as date,

View File

@ -795,10 +795,22 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques
}
defer conn.Close(websocket.StatusAbnormalClosure, "")
var lastReport codersdk.AgentStatsReportResponse
latestStat, err := api.Database.GetLatestAgentStat(r.Context(), workspaceAgent.ID)
if err == nil {
err = json.Unmarshal(latestStat.Payload, &lastReport)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to unmarshal stat payload.",
Detail: err.Error(),
})
return
}
}
// Allow overriding the stat interval for debugging and testing purposes.
ctx := r.Context()
timer := time.NewTicker(api.AgentStatsRefreshInterval)
var lastReport codersdk.AgentStatsReportResponse
for {
err := wsjson.Write(ctx, conn, codersdk.AgentStatsReportRequest{})
if err != nil {