Skip to content

Commit

Permalink
feat(payments): add initial NestJS service load on heartbeat
Browse files Browse the repository at this point in the history
Because:

* We want to load/cache the NestJS services on the first request to the
  app, so that the first request is not slow.
* We should use proper NextJS project organization.

This commit:

* Adds a new route to the app that the loadbalancers utilize, to ensure
  that the NestJS services are loaded before the first request to the
  app.
* Moves internal implementation that shouldn't be routed to, behind the
  underscore directory prefix.
  • Loading branch information
bbangert authored and vbudhram committed Sep 19, 2023
1 parent 278c47e commit cc10cba
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 25 deletions.
16 changes: 16 additions & 0 deletions apps/payments/next/app/%5F_heartbeat__/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { NextResponse } from 'next/server';

import { app } from '../_nestapp/app';

export const dynamic = 'force-dynamic';

export async function GET(request: Request) {
await app.getApp();
const resp = new NextResponse('{}');
resp.headers.set('Content-Type', 'application/json');
return resp;
}
16 changes: 16 additions & 0 deletions apps/payments/next/app/%5F_lbheartbeat__/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { NextResponse } from 'next/server';

import { app } from '../_nestapp/app';

export const dynamic = 'force-dynamic';

export async function GET(request: Request) {
await app.getApp();
const resp = new NextResponse('{}');
resp.headers.set('Content-Type', 'application/json');
return resp;
}
9 changes: 5 additions & 4 deletions apps/payments/next/app/[offeringId]/checkout/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { CartService } from '@fxa/payments/cart';
import { PurchaseDetails, TermsAndPrivacy } from '@fxa/payments/ui/server';

import { getCartData, getContentfulContent } from '../../lib/apiClient';
import { getApp } from '../../nestapp/app';
import { getCartData, getContentfulContent } from '../../_lib/apiClient';
import { app } from '../../_nestapp/app';

interface CheckoutParams {
offeringId: string;
}

export const dynamic = 'force-dynamic';

export default async function Index({ params }: { params: CheckoutParams }) {
// TODO - Fetch Cart ID from cookie
// https://nextjs.org/docs/app/api-reference/functions/cookies
Expand All @@ -21,7 +22,7 @@ export default async function Index({ params }: { params: CheckoutParams }) {
const cartData = getCartData(cartId);
const [contentful, cart] = await Promise.all([contentfulData, cartData]);
/* eslint-disable @typescript-eslint/no-unused-vars */
const cartService = (await getApp()).get(CartService);
const cartService = await app.getCartService();

return (
<>
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { dotenvLoader, fileLoader, TypedConfigModule } from 'nest-typed-config';

import { CartManager, CartService } from '@fxa/payments/cart';
import { AccountDatabaseFactory } from '@fxa/shared/db/mysql/account';
import { AccountDatabaseNestFactory } from '@fxa/shared/db/mysql/account';
import { Module } from '@nestjs/common';

import { RootConfig } from './config';
Expand All @@ -21,6 +21,6 @@ import { RootConfig } from './config';
}),
],
controllers: [],
providers: [AccountDatabaseFactory, CartService, CartManager],
providers: [AccountDatabaseNestFactory, CartService, CartManager],
})
export class AppModule {}
28 changes: 28 additions & 0 deletions apps/payments/next/app/_nestapp/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import 'server-only';

import { CartService } from '@fxa/payments/cart';
import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';

class AppSingleton {
private app!: Awaited<
ReturnType<typeof NestFactory.createApplicationContext>
>;

async getApp() {
if (this.app) return this.app;
this.app = await NestFactory.createApplicationContext(AppModule);
return this.app;
}

async getCartService() {
return (await this.getApp()).get(CartService);
}
}

export const app = new AppSingleton();
File renamed without changes.
17 changes: 0 additions & 17 deletions apps/payments/next/app/nestapp/app.ts

This file was deleted.

2 changes: 1 addition & 1 deletion libs/shared/db/mysql/account/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export { CartFactory } from './lib/factories';
export { setupAccountDatabase, AccountDbProvider } from './lib/setup';
export { testAccountDatabaseSetup } from './lib/tests';
export type { AccountDatabase } from './lib/setup';
export { AccountDatabaseFactory } from './lib/account.provider';
export { AccountDatabaseNestFactory } from './lib/account.provider';
2 changes: 1 addition & 1 deletion libs/shared/db/mysql/account/src/lib/account.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
setupAccountDatabase,
} from './setup';

export const AccountDatabaseFactory: Provider<AccountDatabase> = {
export const AccountDatabaseNestFactory: Provider<AccountDatabase> = {
provide: AccountDbProvider,
useFactory: (mysqlConfig: MySQLConfig) => {
return setupAccountDatabase(mysqlConfig);
Expand Down

0 comments on commit cc10cba

Please sign in to comment.