Skip to content

Commit 2f1f989

Browse files
feat: allow setting DAILY VIDEO region via env (calcom#21939)
* feat: allow setting DAILY VIDEO region via env * add comments * Cleaner approach to Daily video region type assertion --------- Co-authored-by: Alex van Andel <me@alexvanandel.com>
1 parent 2303eb7 commit 2f1f989

2 files changed

Lines changed: 46 additions & 8 deletions

File tree

packages/app-store/dailyvideo/lib/VideoApiAdapter.ts

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@ export interface DailyVideoCallData {
4242
url: string;
4343
}
4444

45+
// Regions available to create DailyVideo Rooms in.
46+
const REGION_CODES = [
47+
"af-south-1",
48+
"ap-northeast-2",
49+
"ap-southeast-1",
50+
"ap-southeast-2",
51+
"ap-south-1",
52+
"eu-central-1",
53+
"eu-west-2",
54+
"sa-east-1",
55+
"us-east-1",
56+
"us-west-2",
57+
] as const;
58+
59+
type RoomGeo = (typeof REGION_CODES)[number];
60+
61+
function getDailyVideoRegionFromEnv(): RoomGeo | undefined {
62+
if (!process?.env?.DAILY_VIDEO_REGION) return;
63+
const isRoomGeo = (value: string): value is RoomGeo => REGION_CODES.includes(value as RoomGeo);
64+
function assertIsDailyVideoRegion(value: string): asserts value is RoomGeo {
65+
if (!isRoomGeo(value)) {
66+
throw new Error(`Invalid region code: ${value}. Must be one of: ${REGION_CODES.join(", ")}`);
67+
}
68+
}
69+
const region = process.env.DAILY_VIDEO_REGION;
70+
assertIsDailyVideoRegion(region);
71+
return region;
72+
}
73+
4574
const isS3StorageEnabled =
4675
process.env.CAL_VIDEO_BUCKET_NAME &&
4776
process.env.CAL_VIDEO_BUCKET_REGION &&
@@ -203,11 +232,15 @@ export const setEnableRecordingUIAndUserIdForOrganizer = async (
203232
};
204233

205234
const DailyVideoApiAdapter = (): VideoApiAdapter => {
206-
async function createOrUpdateMeeting(endpoint: string, event: CalendarEvent): Promise<VideoCallData> {
235+
async function createOrUpdateMeeting(
236+
endpoint: string,
237+
event: CalendarEvent,
238+
region?: RoomGeo
239+
): Promise<VideoCallData> {
207240
if (!event.uid) {
208241
throw new Error("We need need the booking uid to create the Daily reference in DB");
209242
}
210-
const body = await translateEvent(event);
243+
const body = await translateEvent(event, region);
211244
const dailyEvent = await postToDailyAPI(endpoint, body).then(dailyReturnTypeSchema.parse);
212245
const meetingToken = await postToDailyAPI("/meeting-tokens", {
213246
properties: {
@@ -226,7 +259,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
226259
});
227260
}
228261

229-
const translateEvent = async (event: CalendarEvent) => {
262+
const translateEvent = async (event: CalendarEvent, region?: RoomGeo) => {
230263
// Documentation at: https://docs.daily.co/reference#list-rooms
231264
// Adds 14 days from the end of the booking as the expiration date
232265
const exp = Math.round(new Date(event.endTime).getTime() / 1000) + 60 * 60 * 24 * 14;
@@ -248,6 +281,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
248281
return {
249282
privacy: "public",
250283
properties: {
284+
...(region ? { geo: region } : {}),
251285
enable_prejoin_ui: true,
252286
enable_knocking: true,
253287
enable_screenshare: true,
@@ -284,7 +318,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
284318
};
285319
};
286320

287-
async function createInstantMeeting(endTime: string) {
321+
async function createInstantMeeting(endTime: string, region?: RoomGeo) {
288322
// added a 1 hour buffer for room expiration
289323
const exp = Math.round(new Date(endTime).getTime() / 1000) + 60 * 60;
290324
const { scale_plan: scalePlan } = await getDailyAppKeys();
@@ -296,6 +330,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
296330
const body = {
297331
privacy: "public",
298332
properties: {
333+
...(region ? { geo: region } : {}),
299334
enable_prejoin_ui: true,
300335
enable_knocking: true,
301336
enable_screenshare: true,
@@ -347,20 +382,22 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
347382
url: dailyEvent.url,
348383
});
349384
}
350-
385+
// Region on which the DailyVideo room is created can be controlled by ENV var
386+
// undefined region leaves the choice to DailyVideo
387+
const region = getDailyVideoRegionFromEnv();
351388
return {
352389
/** Daily doesn't need to return busy times, so we return empty */
353390
getAvailability: () => {
354391
return Promise.resolve([]);
355392
},
356393
createMeeting: async (event: CalendarEvent): Promise<VideoCallData> =>
357-
createOrUpdateMeeting("/rooms", event),
394+
createOrUpdateMeeting("/rooms", event, region),
358395
deleteMeeting: async (uid: string): Promise<void> => {
359396
await fetcher(`/rooms/${uid}`, { method: "DELETE" });
360397
return Promise.resolve();
361398
},
362399
updateMeeting: (bookingRef: PartialReference, event: CalendarEvent): Promise<VideoCallData> =>
363-
createOrUpdateMeeting(`/rooms/${bookingRef.uid}`, event),
400+
createOrUpdateMeeting(`/rooms/${bookingRef.uid}`, event, region),
364401
getRecordings: async (roomName: string): Promise<GetRecordingsResponseSchema> => {
365402
try {
366403
const res = await fetcher(`/recordings?room_name=${roomName}`).then(
@@ -371,7 +408,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => {
371408
throw new Error("Something went wrong! Unable to get recording");
372409
}
373410
},
374-
createInstantCalVideoRoom: (endTime: string) => createInstantMeeting(endTime),
411+
createInstantCalVideoRoom: (endTime: string) => createInstantMeeting(endTime, region),
375412
getRecordingDownloadLink: async (recordingId: string): Promise<GetAccessLinkResponseSchema> => {
376413
try {
377414
const res = await fetcher(`/recordings/${recordingId}/access-link?valid_for_secs=43200`).then(

turbo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@
281281
"DAILY_SCALE_PLAN",
282282
"DAILY_WEBHOOK_SECRET",
283283
"DAILY_MEETING_ENDED_WEBHOOK_SECRET",
284+
"DAILY_VIDEO_REGION",
284285
"DATABASE_CHUNK_SIZE",
285286
"DATABASE_DIRECT_URL",
286287
"DATABASE_URL",

0 commit comments

Comments
 (0)