Skip to content

Commit b0e48d9

Browse files
committed
feat: add region querying to pre-fetched html
1 parent 5b9c378 commit b0e48d9

File tree

5 files changed

+81
-25
lines changed

5 files changed

+81
-25
lines changed

enterprise/coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
6767

6868
api.AGPL.Options.SetUserGroups = api.setUserGroups
6969
api.AGPL.SiteHandler.AppearanceFetcher = api.fetchAppearanceConfig
70+
api.AGPL.SiteHandler.RegionsFetcher = api.fetchRegions
7071

7172
oauthConfigs := &httpmw.OAuth2Configs{
7273
Github: options.GithubOAuth2Config,

enterprise/coderd/workspaceproxy.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,30 @@ func (api *API) forceWorkspaceProxyHealthUpdate(ctx context.Context) {
3939
// NOTE: this doesn't need a swagger definition since AGPL already has one, and
4040
// this route overrides the AGPL one.
4141
func (api *API) regions(rw http.ResponseWriter, r *http.Request) {
42-
ctx := r.Context()
43-
//nolint:gocritic // this route intentionally requests resources that users
42+
regions, err := api.fetchRegions(r.Context())
43+
if err != nil {
44+
httpapi.InternalServerError(rw, err)
45+
return
46+
}
47+
48+
httpapi.Write(r.Context(), rw, http.StatusOK, regions)
49+
}
50+
51+
func (api *API) fetchRegions(ctx context.Context) (codersdk.RegionsResponse, error) {
52+
//nolint:gocritic // this intentionally requests resources that users
4453
// cannot usually access in order to give them a full list of available
4554
// regions.
4655
ctx = dbauthz.AsSystemRestricted(ctx)
4756

4857
primaryRegion, err := api.AGPL.PrimaryRegion(ctx)
4958
if err != nil {
50-
httpapi.InternalServerError(rw, err)
51-
return
59+
return codersdk.RegionsResponse{}, err
5260
}
5361
regions := []codersdk.Region{primaryRegion}
5462

5563
proxies, err := api.Database.GetWorkspaceProxies(ctx)
5664
if err != nil {
57-
httpapi.InternalServerError(rw, err)
58-
return
65+
return codersdk.RegionsResponse{}, err
5966
}
6067

6168
// Only add additional regions if the proxy health is enabled.
@@ -81,9 +88,9 @@ func (api *API) regions(rw http.ResponseWriter, r *http.Request) {
8188
}
8289
}
8390

84-
httpapi.Write(ctx, rw, http.StatusOK, codersdk.RegionsResponse{
91+
return codersdk.RegionsResponse{
8592
Regions: regions,
86-
})
93+
}, nil
8794
}
8895

8996
// @Summary Update workspace proxy

site/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<meta property="entitlements" content="{{ .Entitlements }}" />
2121
<meta property="appearance" content="{{ .Appearance }}" />
2222
<meta property="experiments" content="{{ .Experiments }}" />
23+
<meta property="regions" content="{{ .Regions }}" />
2324
<!-- We need to set data-react-helmet to be able to override it in the workspace page -->
2425
<link
2526
rel="alternate icon"

site/site.go

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ type Handler struct {
146146
buildInfoJSON string
147147

148148
AppearanceFetcher func(ctx context.Context) (codersdk.AppearanceConfig, error)
149+
RegionsFetcher func(ctx context.Context) (codersdk.RegionsResponse, error)
149150

150151
Entitlements atomic.Pointer[codersdk.Entitlements]
151152
Experiments atomic.Pointer[codersdk.Experiments]
@@ -231,6 +232,7 @@ type htmlState struct {
231232
Entitlements string
232233
Appearance string
233234
Experiments string
235+
Regions string
234236
}
235237

236238
type csrfState struct {
@@ -313,33 +315,64 @@ func (h *Handler) renderHTMLWithState(rw http.ResponseWriter, r *http.Request, f
313315
})
314316
err := eg.Wait()
315317
if err == nil {
316-
user, err := json.Marshal(db2sdk.User(user, orgIDs))
317-
if err == nil {
318-
state.User = html.EscapeString(string(user))
319-
}
320-
entitlements := h.Entitlements.Load()
321-
if entitlements != nil {
322-
entitlements, err := json.Marshal(entitlements)
318+
var wg sync.WaitGroup
319+
wg.Add(1)
320+
go func() {
321+
defer wg.Done()
322+
user, err := json.Marshal(db2sdk.User(user, orgIDs))
323323
if err == nil {
324-
state.Entitlements = html.EscapeString(string(entitlements))
324+
state.User = html.EscapeString(string(user))
325325
}
326+
}()
327+
entitlements := h.Entitlements.Load()
328+
if entitlements != nil {
329+
wg.Add(1)
330+
go func() {
331+
defer wg.Done()
332+
entitlements, err := json.Marshal(entitlements)
333+
if err == nil {
334+
state.Entitlements = html.EscapeString(string(entitlements))
335+
}
336+
}()
326337
}
327338
if h.AppearanceFetcher != nil {
328-
cfg, err := h.AppearanceFetcher(ctx)
329-
if err == nil {
330-
appearance, err := json.Marshal(cfg)
339+
wg.Add(1)
340+
go func() {
341+
defer wg.Done()
342+
cfg, err := h.AppearanceFetcher(ctx)
331343
if err == nil {
332-
state.Appearance = html.EscapeString(string(appearance))
344+
appearance, err := json.Marshal(cfg)
345+
if err == nil {
346+
state.Appearance = html.EscapeString(string(appearance))
347+
}
333348
}
334-
}
349+
}()
350+
}
351+
if h.RegionsFetcher != nil {
352+
wg.Add(1)
353+
go func() {
354+
defer wg.Done()
355+
regions, err := h.RegionsFetcher(ctx)
356+
if err == nil {
357+
regions, err := json.Marshal(regions)
358+
if err == nil {
359+
state.Regions = html.EscapeString(string(regions))
360+
}
361+
}
362+
}()
335363
}
336364
experiments := h.Experiments.Load()
337365
if experiments != nil {
338-
experiments, err := json.Marshal(experiments)
339-
if err == nil {
340-
state.Experiments = html.EscapeString(string(experiments))
341-
}
366+
wg.Add(1)
367+
go func() {
368+
defer wg.Done()
369+
experiments, err := json.Marshal(experiments)
370+
if err == nil {
371+
state.Experiments = html.EscapeString(string(experiments))
372+
}
373+
}()
342374
}
375+
wg.Wait()
343376
}
344377
}
345378

site/src/contexts/ProxyContext.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
9292
)
9393

9494
const queryKey = ["get-proxies"]
95+
const [initialData] = useState(() => {
96+
// Build info is injected by the Coder server into the HTML document.
97+
const regions = document.querySelector("meta[property=regions]")
98+
if (regions) {
99+
const rawContent = regions.getAttribute("content")
100+
try {
101+
return JSON.parse(rawContent as string)
102+
} catch (ex) {
103+
// Ignore this and fetch as normal!
104+
}
105+
}
106+
})
95107
const {
96108
data: proxiesResp,
97109
error: proxiesError,
@@ -100,6 +112,8 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
100112
} = useQuery({
101113
queryKey,
102114
queryFn: getWorkspaceProxies,
115+
staleTime: initialData ? Infinity : undefined,
116+
initialData,
103117
})
104118

105119
// Every time we get a new proxiesResponse, update the latency check

0 commit comments

Comments
 (0)