diff --git a/.changeset/silly-kiwis-count.md b/.changeset/silly-kiwis-count.md new file mode 100644 index 00000000000..1d222623991 --- /dev/null +++ b/.changeset/silly-kiwis-count.md @@ -0,0 +1,5 @@ +--- +'hive': minor +--- + +Add envs for KV namespace on Cloudflare CDN worker diff --git a/packages/services/cdn-worker/src/dev-polyfill.ts b/packages/services/cdn-worker/src/dev-polyfill.ts index 23dd1d650ba..98cb77d080e 100644 --- a/packages/services/cdn-worker/src/dev-polyfill.ts +++ b/packages/services/cdn-worker/src/dev-polyfill.ts @@ -13,4 +13,6 @@ export const env: Env = { SENTRY_DSN: '', SENTRY_ENVIRONMENT: '', SENTRY_RELEASE: '', + // eslint-disable-next-line no-process-env + KV_STORAGE_BASE_URL: process.env.KV_STORAGE_BASE_URL, }; diff --git a/packages/services/cdn-worker/src/dev.ts b/packages/services/cdn-worker/src/dev.ts index 1945df77cb4..18d86569c80 100644 --- a/packages/services/cdn-worker/src/dev.ts +++ b/packages/services/cdn-worker/src/dev.ts @@ -27,6 +27,7 @@ const artifactStorageReader = new ArtifactStorageReader(s3, null, null, null); const handleRequest = createRequestHandler({ isKeyValid: createIsKeyValid({ + kvStorageBaseUrl: env.KV_STORAGE_BASE_URL, artifactStorageReader, getCache: null, waitUntil: null, @@ -52,6 +53,7 @@ const handleRequest = createRequestHandler({ const handleArtifactRequest = createArtifactRequestHandler({ isKeyValid: createIsKeyValid({ + kvStorageBaseUrl: env.KV_STORAGE_BASE_URL, artifactStorageReader, getCache: null, waitUntil: null, diff --git a/packages/services/cdn-worker/src/env.ts b/packages/services/cdn-worker/src/env.ts index fae1114bf99..6471b1d9bc2 100644 --- a/packages/services/cdn-worker/src/env.ts +++ b/packages/services/cdn-worker/src/env.ts @@ -16,4 +16,11 @@ export type Env = { * Id of the release */ SENTRY_RELEASE: string; + /** + * Base URL of the KV storage, used to fetch the schema from the KV storage. + * If not provided, the schema will be fetched from default KV storage value. + * + * @default https://key-cache.graphql-hive.com + */ + KV_STORAGE_BASE_URL?: string; }; diff --git a/packages/services/cdn-worker/src/index.ts b/packages/services/cdn-worker/src/index.ts index 6a223a229aa..6e12b6c5312 100644 --- a/packages/services/cdn-worker/src/index.ts +++ b/packages/services/cdn-worker/src/index.ts @@ -41,6 +41,14 @@ type Env = { R2_ANALYTICS: AnalyticsEngine; S3_ANALYTICS: AnalyticsEngine; KEY_VALIDATION_ANALYTICS: AnalyticsEngine; + + /** + * Base URL of the KV storage, used to fetch the schema from the KV storage. + * If not provided, the schema will be fetched from default KV storage value. + * + * @default https://key-cache.graphql-hive.com + */ + KV_STORAGE_BASE_URL?: string; }; const handler: ExportedHandler = { @@ -108,6 +116,7 @@ const handler: ExportedHandler = { ); const isKeyValid = createIsKeyValid({ + kvStorageBaseUrl: env.KV_STORAGE_BASE_URL, waitUntil: p => ctx.waitUntil(p), getCache: () => caches.open('artifacts-auth'), artifactStorageReader, diff --git a/packages/services/cdn-worker/src/key-validation.ts b/packages/services/cdn-worker/src/key-validation.ts index 746106c86a7..420b8b7956c 100644 --- a/packages/services/cdn-worker/src/key-validation.ts +++ b/packages/services/cdn-worker/src/key-validation.ts @@ -11,6 +11,7 @@ type WaitUntil = (promise: Promise) => void; type GetCache = () => Promise; type CreateKeyValidatorDeps = { + kvStorageBaseUrl?: string; waitUntil: null | WaitUntil; artifactStorageReader: ArtifactStorageReader; getCache: null | GetCache; @@ -34,6 +35,7 @@ export const createIsKeyValid = }; const handleLegacyCDNAccessToken = async (args: { + kvStorageBaseUrl?: string; targetId: string; accessToken: string; artifactStorageReader: ArtifactStorageReader; @@ -49,7 +51,7 @@ const handleLegacyCDNAccessToken = async (args: { if (requestCache) { const cacheKey = new Request( [ - 'https://key-cache.graphql-hive.com', + args.kvStorageBaseUrl ?? 'https://key-cache.graphql-hive.com', 'legacy', args.targetId, encodeURIComponent(args.accessToken), @@ -150,9 +152,12 @@ async function handleCDNAccessToken( if (requestCache) { const cacheKey = new Request( - ['http://key-cache.graphql-hive.com', 'v1', targetId, encodeURIComponent(accessToken)].join( - '/', - ), + [ + deps.kvStorageBaseUrl ?? 'https://key-cache.graphql-hive.com', + 'v1', + targetId, + encodeURIComponent(accessToken), + ].join('/'), { method: 'GET', }, diff --git a/packages/services/server/README.md b/packages/services/server/README.md index 10f8fc5981d..35c5a8f658a 100644 --- a/packages/services/server/README.md +++ b/packages/services/server/README.md @@ -45,6 +45,7 @@ The GraphQL API for GraphQL Hive. | `S3_MIRROR_PUBLIC_URL` | No | The public URL of the S3, in case it differs from the `S3_ENDPOINT`. | `http://localhost:8083` | | `CDN_API` | No | Whether the CDN exposed via API is enabled. | `1` (enabled) or `0` (disabled) | | `CDN_API_BASE_URL` | No (Yes if `CDN_API` is set to `1`) | The public base url of the API service. | `http://localhost:8082` | +| `CDN_API_KV_BASE_URL` | No (**Optional** if `CDN_API` is set to `1`) | The base URL for the KV for API Provider. Used for scenarios where we cache CDN access. | `https://key-cache.graphql-hive.com` | | `SUPERTOKENS_CONNECTION_URI` | **Yes** | The URI of the SuperTokens instance. | `http://127.0.0.1:3567` | | `SUPERTOKENS_API_KEY` | **Yes** | The API KEY of the SuperTokens instance. | `iliketurtlesandicannotlie` | | `AUTH_GITHUB` | No | Whether login via GitHub should be allowed | `1` (enabled) or `0` (disabled) | @@ -89,12 +90,13 @@ The GraphQL API for GraphQL Hive. If you are self-hosting GraphQL Hive, you can ignore this section. It is only required for the Cloud version. -| Name | Required | Description | Example Value | -| ------------------------- | ------------------------------------ | -------------------------------------------------------------- | --------------------------------------------------- | -| `COMMERCE_ENDPOINT` | **Yes** | The endpoint of the commerce service. | `http://127.0.0.1:4012` | -| `CDN_CF` | No | Whether the CDN is enabled. | `1` (enabled) or `0` (disabled) | -| `CDN_CF_BASE_URL` | No (**Yes** if `CDN` is `1`) | The base URL of the cdn. | `https://cdn.graphql-hive.com` | -| `HIVE_USAGE` | No | Whether usage reporting for the GraphQL API to Hive is enabled | `1` (enabled) or `0` (disabled) | -| `HIVE_USAGE_TARGET` | No (**Yes** if `HIVE` is set to `1`) | The target to which the usage data should be reported | `the-guild/graphql-hive/development` | -| `HIVE_USAGE_ACCESS_TOKEN` | No (**Yes** if `HIVE` is set to `1`) | The internal endpoint key. | `iliketurtles` | -| `HIVE_USAGE_ENDPOINT` | No | The endpoint used for usage reporting. | `http://app.graphql-hive.com/usage` (default value) | +| Name | Required | Description | Example Value | +| ------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | +| `COMMERCE_ENDPOINT` | **Yes** | The endpoint of the commerce service. | `http://127.0.0.1:4012` | +| `CDN_CF` | No | Whether the CDN is enabled. | `1` (enabled) or `0` (disabled) | +| `CDN_CF_BASE_URL` | No (**Yes** if `CDN` is `1`) | The base URL of the cdn. | `https://cdn.graphql-hive.com` | +| `CDN_CF_KV_BASE_URL` | No (**Optional** if `CDN` is `1`) | The base URL for the key-value store used for CDN access key validation caching when using the Cloudflare provider. | `https://key-cache.graphql-hive.com` | +| `HIVE_USAGE` | No | Whether usage reporting for the GraphQL API to Hive is enabled | `1` (enabled) or `0` (disabled) | +| `HIVE_USAGE_TARGET` | No (**Yes** if `HIVE` is set to `1`) | The target to which the usage data should be reported | `the-guild/graphql-hive/development` | +| `HIVE_USAGE_ACCESS_TOKEN` | No (**Yes** if `HIVE` is set to `1`) | The internal endpoint key. | `iliketurtles` | +| `HIVE_USAGE_ENDPOINT` | No | The endpoint used for usage reporting. | `http://app.graphql-hive.com/usage` (default value) | diff --git a/packages/services/server/src/environment.ts b/packages/services/server/src/environment.ts index 00f74df3b9f..5ada401dab5 100644 --- a/packages/services/server/src/environment.ts +++ b/packages/services/server/src/environment.ts @@ -118,6 +118,7 @@ const CdnCFModel = zod.union([ zod.object({ CDN_CF: zod.literal('1'), CDN_CF_BASE_URL: zod.string(), + CDN_CF_KV_BASE_URL: emptyString(zod.string().url().optional()), }), ]); @@ -128,6 +129,7 @@ const CdnApiModel = zod.union([ zod.object({ CDN_API: zod.literal('1'), CDN_API_BASE_URL: zod.string(), + CDN_API_KV_BASE_URL: emptyString(zod.string().url().optional()), }), ]); @@ -447,9 +449,16 @@ export const env = { cdnCf.CDN_CF === '1' ? { baseUrl: cdnCf.CDN_CF_BASE_URL, + kv: cdnCf.CDN_CF_KV_BASE_URL ? { baseUrl: cdnCf.CDN_CF_KV_BASE_URL } : null, + } + : null, + api: + cdnApi.CDN_API === '1' + ? { + baseUrl: cdnApi.CDN_API_BASE_URL, + kv: cdnApi.CDN_API_KV_BASE_URL ? { baseUrl: cdnApi.CDN_API_KV_BASE_URL } : null, } : null, - api: cdnApi.CDN_API === '1' ? { baseUrl: cdnApi.CDN_API_BASE_URL } : null, }, }, s3: { diff --git a/packages/services/server/src/index.ts b/packages/services/server/src/index.ts index bf29d4d0688..cc673faf4fa 100644 --- a/packages/services/server/src/index.ts +++ b/packages/services/server/src/index.ts @@ -631,6 +631,7 @@ export async function main() { const artifactHandler = createArtifactRequestHandler({ isKeyValid: createIsKeyValid({ + kvStorageBaseUrl: env.cdn.providers.api.kv?.baseUrl, artifactStorageReader, analytics: null, breadcrumb(message: string) {