Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4996df1

Browse files
committed
chore: Add watch workspace endpoint
1 parent 98ccd0e commit 4996df1

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ func New(options *Options) (http.Handler, func()) {
307307
r.Route("/autostop", func(r chi.Router) {
308308
r.Put("/", api.putWorkspaceAutostop)
309309
})
310+
r.HandleFunc("/watch", api.watchWorkspace)
310311
})
311312
r.Route("/workspacebuilds/{workspacebuild}", func(r chi.Router) {
312313
r.Use(

coderd/workspaces.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ import (
77
"errors"
88
"fmt"
99
"net/http"
10+
"time"
1011

12+
"cdr.dev/slog"
1113
"github.com/go-chi/chi/v5"
1214
"github.com/google/uuid"
1315
"github.com/moby/moby/pkg/namesgenerator"
1416
"golang.org/x/sync/errgroup"
1517
"golang.org/x/xerrors"
18+
"nhooyr.io/websocket"
19+
"nhooyr.io/websocket/wsjson"
1620

1721
"github.com/coder/coder/coderd/autobuild/schedule"
1822
"github.com/coder/coder/coderd/database"
@@ -496,6 +500,94 @@ func (api *api) putWorkspaceAutostop(rw http.ResponseWriter, r *http.Request) {
496500
}
497501
}
498502

503+
func (api *api) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
504+
workspace := httpmw.WorkspaceParam(r)
505+
506+
c, err := websocket.Accept(rw, r, &websocket.AcceptOptions{
507+
// Fix for Safari 15.1:
508+
// There is a bug in latest Safari in which compressed web socket traffic
509+
// isn't handled correctly. Turning off compression is a workaround:
510+
// https://github.com/nhooyr/websocket/issues/218
511+
CompressionMode: websocket.CompressionDisabled,
512+
})
513+
if err != nil {
514+
api.Logger.Warn(r.Context(), "accept websocket connection", slog.Error(err))
515+
return
516+
}
517+
defer c.Close(websocket.StatusInternalError, "internal error")
518+
519+
ctx := c.CloseRead(r.Context())
520+
521+
// Send a heartbeat every 15 seconds to avoid the websocket being killed.
522+
go func() {
523+
ticker := time.NewTicker(time.Second * 15)
524+
defer ticker.Stop()
525+
526+
for {
527+
select {
528+
case <-ctx.Done():
529+
return
530+
case <-ticker.C:
531+
err := c.Ping(ctx)
532+
if err != nil {
533+
return
534+
}
535+
}
536+
}
537+
}()
538+
539+
t := time.NewTicker(time.Second * 1)
540+
defer t.Stop()
541+
for {
542+
select {
543+
case <-t.C:
544+
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspace.ID)
545+
if err != nil {
546+
_ = wsjson.Write(ctx, c, httpapi.Response{
547+
Message: fmt.Sprintf("get workspace: %s", err),
548+
})
549+
return
550+
}
551+
build, err := api.Database.GetWorkspaceBuildByWorkspaceIDWithoutAfter(r.Context(), workspace.ID)
552+
if err != nil {
553+
_ = wsjson.Write(ctx, c, httpapi.Response{
554+
Message: fmt.Sprintf("get workspace build: %s", err),
555+
})
556+
return
557+
}
558+
var (
559+
group errgroup.Group
560+
job database.ProvisionerJob
561+
template database.Template
562+
owner database.User
563+
)
564+
group.Go(func() (err error) {
565+
job, err = api.Database.GetProvisionerJobByID(r.Context(), build.JobID)
566+
return err
567+
})
568+
group.Go(func() (err error) {
569+
template, err = api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
570+
return err
571+
})
572+
group.Go(func() (err error) {
573+
owner, err = api.Database.GetUserByID(r.Context(), workspace.OwnerID)
574+
return err
575+
})
576+
err = group.Wait()
577+
if err != nil {
578+
_ = wsjson.Write(ctx, c, httpapi.Response{
579+
Message: fmt.Sprintf("fetch resource: %s", err),
580+
})
581+
return
582+
}
583+
584+
_ = wsjson.Write(ctx, c, convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template, owner))
585+
case <-ctx.Done():
586+
return
587+
}
588+
}
589+
}
590+
499591
func convertWorkspaces(ctx context.Context, db database.Store, workspaces []database.Workspace) ([]codersdk.Workspace, error) {
500592
workspaceIDs := make([]uuid.UUID, 0, len(workspaces))
501593
templateIDs := make([]uuid.UUID, 0, len(workspaces))

0 commit comments

Comments
 (0)