Skip to content

Commit

Permalink
Update dependencies (#288)
Browse files Browse the repository at this point in the history
  • Loading branch information
kibertoad authored Sep 14, 2023
1 parent e0057ef commit 942b4bf
Show file tree
Hide file tree
Showing 11 changed files with 650 additions and 648 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ---- Base Node ----
FROM node:20.5.1-bookworm-slim as base
FROM node:20.6.1-bookworm-slim as base

RUN set -ex;\
apt-get update -y; \
Expand Down
1,152 changes: 546 additions & 606 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,35 @@
},
"dependencies": {
"@fastify/auth": "^4.3.0",
"@fastify/awilix": "^3.1.0",
"@fastify/awilix": "^3.2.0",
"@fastify/cors": "^8.3.0",
"@fastify/helmet": "^11.0.0",
"@fastify/jwt": "^7.2.0",
"@fastify/helmet": "^11.1.0",
"@fastify/jwt": "^7.2.1",
"@fastify/schedule": "^4.1.1",
"@fastify/swagger": "^8.9.0",
"@fastify/swagger": "^8.10.0",
"@fastify/swagger-ui": "^1.9.3",
"@lokalise/fastify-extras": "^12.0.0",
"@lokalise/fastify-extras": "^14.1.0",
"@lokalise/node-core": "^6.3.2",
"@lokalise/zod-extras": "^2.0.0",
"@message-queue-toolkit/amqp": "^3.5.0",
"@message-queue-toolkit/core": "^3.5.0",
"@message-queue-toolkit/core": "^3.6.0",
"@prisma/client": "^5.2.0",
"@prisma/instrumentation": "^5.2.0",
"amqplib": "^0.10.3",
"awilix": "^8.0.1",
"awilix-manager": "^3.1.0",
"croner": "^7.0.1",
"dotenv": "^16.3.1",
"fastify": "^4.22.2",
"fastify": "^4.23.2",
"fastify-custom-healthcheck": "^3.1.0",
"fastify-graceful-shutdown": "^3.5.1",
"fastify-metrics": "^10.3.0",
"fastify-no-icon": "^6.0.0",
"fastify-type-provider-zod": "^1.1.9",
"ioredis": "^5.3.2",
"jsonwebtoken": "^9.0.2",
"layered-loader": "^11.0.1",
"newrelic": "10.6.2",
"layered-loader": "^12.3.0",
"newrelic": "11.1.0",
"pino": "^8.15.1",
"pino-pretty": "^10.2.0",
"redis-semaphore": "^5.5.0",
Expand All @@ -74,8 +74,8 @@
"@types/jsonwebtoken": "^9.0.2",
"@types/newrelic": "^9.14.0",
"@types/node": "^20.6.0",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"@typescript-eslint/eslint-plugin": "^6.7.0",
"@typescript-eslint/parser": "^6.7.0",
"@vitest/coverage-v8": "^0.34.4",
"cpy-cli": "^5.0.0",
"cross-env": "^7.0.3",
Expand Down
21 changes: 17 additions & 4 deletions src/app.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { buildClient, sendGet } from '@lokalise/node-core'
import type { FastifyInstance } from 'fastify'

import type { TestContext } from '../test/TestContext'
import { createTestContext } from '../test/TestContext'

import { getApp } from './app'
Expand All @@ -21,7 +20,7 @@ describe('app', () => {

describe('healthcheck', () => {
it('Returns health check information', async () => {
const response = await app.inject().get('/health').end()
const response = await app.inject().get('/').end()

expect(response.json()).toMatchObject({
healthChecks: {
Expand All @@ -34,12 +33,15 @@ describe('app', () => {
})

it('Returns public health check information', async () => {
const response = await app.inject().get('/').end()
const response = await app.inject().get('/health').end()

expect(response.json()).toMatchObject({
gitCommitSha: 'sha',
heartbeat: 'HEALTHY',
status: 'OK',
checks: {
mysql: 'HEALTHY',
redis: 'HEALTHY',
},
version: '1',
})
expect(response.statusCode).toBe(200)
Expand All @@ -52,6 +54,17 @@ describe('app', () => {

expect(response.result.statusCode).toBe(200)
})

it('Returns Prometheus healthcheck metrics', async () => {
const response = await sendGet(buildClient('http://127.0.0.1:9080'), '/metrics')

expect(response.result.statusCode).toBe(200)
expect(response.result.body).toContain('redis_availability 1')
expect(response.result.body).toContain('redis_latency_msecs ')

expect(response.result.body).toContain('mysql_availability 1')
expect(response.result.body).toContain('mysql_latency_msecs ')
})
})

describe('OpenAPI documentation', () => {
Expand Down
45 changes: 34 additions & 11 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
requestContextProviderPlugin,
publicHealthcheckPlugin,
amplitudePlugin,
healthcheckMetricsPlugin,
} from '@lokalise/fastify-extras'
import { resolveGlobalErrorLogObject } from '@lokalise/node-core'
import { resolveAmqpConnection } from '@message-queue-toolkit/amqp'
Expand Down Expand Up @@ -52,6 +53,7 @@ import {
redisHealthCheck,
registerHealthChecks,
runAllHealthchecks,
wrapHealthCheckForPrometheus,
} from './infrastructure/healthchecks'
import { resolveLoggerConfiguration } from './infrastructure/logger'
import { getRoutes } from './modules/routes'
Expand Down Expand Up @@ -226,9 +228,18 @@ export async function getApp(
},
)

if (configOverrides.monitoringEnabled) {
await app.register(metricsPlugin, {
bindAddress: appConfig.bindAddress,
errorObjectResolver: resolveGlobalErrorLogObject,
loggerOptions: loggerConfig,
disablePrometheusRequestLogging: true,
})
}

if (configOverrides.healthchecksEnabled !== false) {
await app.register(customHealthCheck, {
path: '/health',
path: '/',
logLevel: 'warn',
info: {
env: appConfig.nodeEnv,
Expand All @@ -239,25 +250,37 @@ export async function getApp(
exposeFailure: false,
})
await app.register(publicHealthcheckPlugin, {
healthChecks: [dbHealthCheck, redisHealthCheck],
url: '/health',
healthChecks: [
{
name: 'mysql',
isMandatory: true,
checker: dbHealthCheck,
},
{
name: 'redis',
isMandatory: true,
checker: redisHealthCheck,
},
],
responsePayload: {
version: appConfig.appVersion,
gitCommitSha: appConfig.gitCommitSha,
status: 'OK',
},
})

if (configOverrides.monitoringEnabled) {
await app.register(healthcheckMetricsPlugin, {
healthChecks: [
wrapHealthCheckForPrometheus(redisHealthCheck, 'redis'),
wrapHealthCheckForPrometheus(dbHealthCheck, 'mysql'),
],
})
}
}
await app.register(requestContextProviderPlugin)

// Vendor-specific plugins
if (configOverrides.monitoringEnabled) {
await app.register(metricsPlugin, {
bindAddress: appConfig.bindAddress,
errorObjectResolver: resolveGlobalErrorLogObject,
loggerOptions: loggerConfig,
disablePrometheusRequestLogging: true,
})
}
await app.register(newrelicTransactionManagerPlugin, {
isEnabled: config.vendors.newrelic.isEnabled,
})
Expand Down
3 changes: 2 additions & 1 deletion src/infrastructure/commonDiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import type { Config } from './config'
import type { ExternalDependencies } from './diConfig'
import { SINGLETON_CONFIG } from './diConfig'

export type CommonDiConfig = Record<keyof CommonDependencies, Resolver<unknown>>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type CommonDiConfig = Record<keyof CommonDependencies, Resolver<any>>

export function resolveCommonDiConfig(
dependencies: ExternalDependencies = { logger: globalLogger },
Expand Down
3 changes: 2 additions & 1 deletion src/infrastructure/diConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ export function registerDependencies(
}
}

type DiConfig = Record<keyof Dependencies, Resolver<unknown>>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type DiConfig = Record<keyof Dependencies, Resolver<any>>

export type Dependencies = CommonDependencies & UsersModuleDependencies

Expand Down
41 changes: 30 additions & 11 deletions src/infrastructure/healthchecks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { types } from 'node:util'

import type { HealthCheck } from '@lokalise/fastify-extras'
import type {
HealthChecker,
HealthcheckResult,
PrometheusHealthCheck,
} from '@lokalise/fastify-extras'
import type { Either } from '@lokalise/node-core'
import { executeAsyncAndHandleGlobalErrors } from '@lokalise/node-core'
import { executeSettleAllAndHandleGlobalErrors } from '@lokalise/node-core'
import type { FastifyInstance } from 'fastify'

export const wrapHealthCheck = (app: FastifyInstance, healthCheck: HealthCheck) => {
export const wrapHealthCheck = (app: FastifyInstance, healthCheck: HealthChecker) => {
return async () => {
const response = await healthCheck(app)
if (response.error) {
Expand All @@ -14,7 +18,26 @@ export const wrapHealthCheck = (app: FastifyInstance, healthCheck: HealthCheck)
}
}

export const redisHealthCheck: HealthCheck = async (app): Promise<Either<Error, true>> => {
export const wrapHealthCheckForPrometheus = (
healthCheck: HealthChecker,
healthcheckName: string,
): PrometheusHealthCheck => {
return {
name: healthcheckName,
checker: async (app: FastifyInstance): Promise<HealthcheckResult> => {
const startTime = Date.now()
const response = await healthCheck(app)
const checkTimeInMsecs = Date.now() - startTime

return {
checkPassed: !!response.result,
checkTimeInMsecs,
}
},
}
}

export const redisHealthCheck: HealthChecker = async (app): Promise<Either<Error, true>> => {
const redis = app.diContainer.cradle.redis

try {
Expand All @@ -28,7 +51,7 @@ export const redisHealthCheck: HealthCheck = async (app): Promise<Either<Error,

return { result: true }
}
export const dbHealthCheck: HealthCheck = async (app): Promise<Either<Error, true>> => {
export const dbHealthCheck: HealthChecker = async (app): Promise<Either<Error, true>> => {
const prisma = app.diContainer.cradle.prisma
try {
const response = await prisma.$queryRaw`SELECT 1`
Expand Down Expand Up @@ -57,12 +80,8 @@ export function registerHealthChecks(app: FastifyInstance) {
}

export async function runAllHealthchecks(app: FastifyInstance) {
return executeAsyncAndHandleGlobalErrors(
() =>
Promise.all([
wrapHealthCheck(app, dbHealthCheck)(),
wrapHealthCheck(app, redisHealthCheck)(),
]),
return executeSettleAllAndHandleGlobalErrors(
[wrapHealthCheck(app, dbHealthCheck)(), wrapHealthCheck(app, redisHealthCheck)()],
false,
)
}
4 changes: 4 additions & 0 deletions src/modules/users/datasources/UserDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ export class UserDataSource implements DataSource<User> {
get(userId: string): Promise<User | null> {
return this.userRepository.getUser(Number.parseInt(userId))
}

getMany(keys: string[]): Promise<User[]> {
return this.userRepository.getUsers(keys.map(Number.parseInt))
}
}
3 changes: 2 additions & 1 deletion src/modules/users/diConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const IN_MEMORY_CONFIGURATION_BASE: InMemoryCacheConfiguration = {
cacheType: 'fifo-object',
}

type UsersDiConfig = Record<keyof UsersModuleDependencies, Resolver<unknown>>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type UsersDiConfig = Record<keyof UsersModuleDependencies, Resolver<any>>

export type UsersModuleDependencies = {
userRepository: UserRepository
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/jwtTokenPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function plugin(
fastify.addHook(
'onRequest',
(req: FastifyRequest, res: FastifyReply, done: HookHandlerDoneFunction) => {
if (pluginOptions.skipList.has(req.routerPath)) {
if (pluginOptions.skipList.has(req.routeOptions.url)) {
return done()
}

Expand Down

0 comments on commit 942b4bf

Please sign in to comment.