Compare commits
3 Commits
70d12615b8
...
b25085bcd7
| Author | SHA1 | Date | |
|---|---|---|---|
| b25085bcd7 | |||
| cf6c312e04 | |||
| da4ce37aff |
@@ -11,12 +11,30 @@ import (
|
||||
"tanabata/backend/internal/db"
|
||||
)
|
||||
|
||||
// appName tags every connection as application_name, so the backend's sessions
|
||||
// are identifiable in pg_stat_activity and server logs (and distinguishable from
|
||||
// e.g. goose migrations or a psql shell).
|
||||
const appName = "tanabata-backend"
|
||||
|
||||
// NewPool creates and validates a *pgxpool.Pool from the given connection URL.
|
||||
// The pool is ready to use; the caller is responsible for closing it.
|
||||
func NewPool(ctx context.Context, url string) (*pgxpool.Pool, error) {
|
||||
pool, err := pgxpool.New(ctx, url)
|
||||
cfg, err := pgxpool.ParseConfig(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pgxpool.New: %w", err)
|
||||
return nil, fmt.Errorf("pgxpool.ParseConfig: %w", err)
|
||||
}
|
||||
// Set application_name unless the operator already specified one in the DSN
|
||||
// (or via PGAPPNAME), so an explicit override still wins.
|
||||
if cfg.ConnConfig.RuntimeParams == nil {
|
||||
cfg.ConnConfig.RuntimeParams = map[string]string{}
|
||||
}
|
||||
if cfg.ConnConfig.RuntimeParams["application_name"] == "" {
|
||||
cfg.ConnConfig.RuntimeParams["application_name"] = appName
|
||||
}
|
||||
|
||||
pool, err := pgxpool.NewWithConfig(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("pgxpool.NewWithConfig: %w", err)
|
||||
}
|
||||
if err := pool.Ping(ctx); err != nil {
|
||||
pool.Close()
|
||||
|
||||
@@ -128,8 +128,13 @@ async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
|
||||
invalidateSectionCache(path, (init?.method ?? 'GET').toUpperCase());
|
||||
|
||||
// A success doesn't guarantee a JSON body: 204 never has one, and some 200/201
|
||||
// responses (e.g. POST /pools/:id/files) complete with an empty body. Parsing
|
||||
// those as JSON throws, so read the text first and only parse when present —
|
||||
// otherwise an empty 201 would surface as a spurious "failed" error.
|
||||
if (res.status === 204) return undefined as T;
|
||||
return res.json();
|
||||
const text = await res.text();
|
||||
return (text ? JSON.parse(text) : undefined) as T;
|
||||
}
|
||||
|
||||
/** Upload with XHR so we can track progress via onProgress(0–100). */
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Vendored
+14
-7
@@ -35,21 +35,28 @@
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/images/android-icon-192x192.png",
|
||||
"src": "/images/pwa-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/images/apple-icon-180x180.png",
|
||||
"sizes": "180x180",
|
||||
"type": "image/png"
|
||||
"src": "/images/pwa-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/images/ms-icon-310x310.png",
|
||||
"sizes": "310x310",
|
||||
"src": "/images/pwa-maskable-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/images/pwa-maskable-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user