Skip to content

Commit

Permalink
standardize stream-metadata service config (#727)
Browse files Browse the repository at this point in the history
stream-metadata config to get it ready for deployment. 

Kerem + Tak co-authoring changes.

---------

Co-authored-by: Tak Wai Wong <[email protected]>
  • Loading branch information
mechanical-turk and tak-hntlabs authored Aug 14, 2024
1 parent 51dd350 commit f4054fc
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 43 deletions.
File renamed without changes.
7 changes: 7 additions & 0 deletions packages/stream-metadata/.prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @see https://prettier.io/docs/en/configuration.html
* @type {import("prettier").Config}
*/
module.exports = {
...require("@river-build/prettier-config"),
};
1 change: 1 addition & 0 deletions packages/stream-metadata/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ Start the river image service:
# if the dependencies are not present, run:
# ./<projectRoot>/scripts/start_dev.sh

cp .env.local.sample .env.local
yarn dev
```
8 changes: 6 additions & 2 deletions packages/stream-metadata/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,29 @@
"scripts": {
"build": "node ./esbuild.config.mjs",
"dev": "yarn build && NODE_ENV=development node --experimental-detect-module ./dist/node_esbuild.cjs",
"prettier": "prettier --config ../../packages/prettier-config/config.js --ignore-path .prettierignore .",
"prettier": "prettier --config ../prettier-config/config.js --ignore-path .prettierignore .",
"start": "NODE_ENV=production node --experimental-detect-module ./dist/node_esbuild.cjs"
},
"dependencies": {
"@bufbuild/buf": "^1.32.0",
"@bufbuild/protobuf": "^1.9.0",
"@connectrpc/connect": "^1.4.0",
"@connectrpc/connect-web": "^1.4.0",
"@fastify/cors": "^9.0.1",
"@river-build/generated": "workspace:^",
"@river-build/proto": "workspace:^",
"@river-build/sdk": "workspace:^",
"@river-build/web3": "workspace:^",
"dotenv": "^16.4.5",
"ethers": "^5.7.2",
"fastify": "^4.28.1",
"magic-bytes.js": "^1.10.0",
"viem": "^1.18.2"
"zod": "^3.21.4"
},
"devDependencies": {
"@river-build/prettier-config": "workspace:^",
"@types/node": "^20.5.0",
"@typescript-eslint/parser": "^7.14.1",
"esbuild": "^0.21.5",
"rollup": "^4.18.1",
"ts-node": "^10.9.1",
Expand Down
19 changes: 0 additions & 19 deletions packages/stream-metadata/src/contracts.ts

This file was deleted.

28 changes: 18 additions & 10 deletions packages/stream-metadata/src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import * as dotenv from 'dotenv'
import { getWeb3Deployment } from '@river-build/web3'
import { z } from 'zod'

import { Config } from './types'
import { getWeb3Deployment } from '@river-build/web3'

const isDev = process.env.NODE_ENV === 'development'
const envFile = isDev ? '.env.localhost' : '.env'
const IntStringSchema = z.string().regex(/^[0-9]+$/)
const NumberFromIntStringSchema = IntStringSchema.transform((str) => parseInt(str, 10))

const envSchema = z.object({
RIVER_ENV: z.string(),
RIVER_CHAIN_RPC_URL: z.string().url(),
PORT: NumberFromIntStringSchema,
})

dotenv.config({
path: envFile,
path: ['.env', '.env.local'],
})

export const SERVER_PORT = parseInt(process.env.PORT ?? '443', 10)
export const config = makeConfig(process.env.RIVER_ENV, process.env.RIVER_CHAIN_RPC_URL)
// eslint-disable-next-line no-process-env -- this is the only line where we're allowed to use process.env
const env = envSchema.parse(process.env)

export const config = makeConfig(env.RIVER_ENV, env.RIVER_CHAIN_RPC_URL, env.PORT)

function makeConfig(
riverEnv = 'omega',
riverChainRpcUrl = 'https://mainnet.rpc.river.build/http',
): Config {
function makeConfig(riverEnv: string, riverChainRpcUrl: string, port: number): Config {
const web3Config = getWeb3Deployment(riverEnv)
return {
...web3Config,
port,
riverEnv,
riverChainRpcUrl,
}
Expand All @@ -28,6 +35,7 @@ function makeConfig(
console.log('config', {
riverEnv: config.riverEnv,
chainId: config.river.chainId,
port: config.port,
riverRegistry: config.river.addresses.riverRegistry,
riverChainRpcUrl: config.riverChainRpcUrl,
})
41 changes: 30 additions & 11 deletions packages/stream-metadata/src/node.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import Fastify from 'fastify'
import { Server as HTTPSServer } from 'https'
import { SERVER_PORT } from './environment'

import Fastify from 'fastify'
import cors from '@fastify/cors'

import { handleImageRequest } from './handleImageRequest'
import { handleMetadataRequest } from './handleMetadataRequest'
import { config } from './environment'

// Set the process title to 'fetch-image' so it can be easily identified
// or killed with `pkill fetch-image`
Expand All @@ -13,10 +15,20 @@ const server = Fastify({
logger: true,
})

server.register(cors, {
origin: '*', // Allow any origin
methods: ['GET'], // Allowed HTTP methods
})
async function registerPlugins() {
try {
await server.register(cors, {
origin: '*', // Allow any origin
methods: ['GET'], // Allowed HTTP methods
})
console.info('CORS registered successfully')
} catch (err) {
console.error('Error registering CORS', err)
process.exit(1) // Exit the process if registration fails
}
}

registerPlugins()

server.get('/space/:spaceAddress', async (request, reply) => {
const { spaceAddress } = request.params as { spaceAddress?: string }
Expand Down Expand Up @@ -49,8 +61,8 @@ function getServerInfo() {
}

// Type guard to check if error has code property
function isAddressInUseError(err: any): err is NodeJS.ErrnoException {
return err && typeof err === 'object' && 'code' in err
function isAddressInUseError(err: unknown): err is NodeJS.ErrnoException {
return err instanceof Error && 'code' in err && err.code === 'EADDRINUSE'
}

// Function to start the server on the first available port
Expand All @@ -62,9 +74,9 @@ async function startServer(port: number) {
server.log.info(`Server listening on ${addressInfo.address}:${addressInfo.port}`)
}
} catch (err) {
if (isAddressInUseError(err) && err.code === 'EADDRINUSE') {
if (isAddressInUseError(err)) {
server.log.warn(`Port ${port} is in use, trying port ${port + 1}`)
startServer(port + 1) // Try the next port
await startServer(port + 1) // Try the next port
} else {
server.log.error(err)
process.exit(1)
Expand All @@ -84,4 +96,11 @@ process.on('SIGTERM', async () => {
})

// Start the server on the port set in the .env, or the next available port
startServer(SERVER_PORT)
startServer(config.port)
.then(() => {
console.log('Server started')
})
.catch((err) => {
console.error('Error starting server', err)
process.exit(1)
})
1 change: 1 addition & 0 deletions packages/stream-metadata/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getWeb3Deployment } from '@river-build/web3'

export interface Config extends ReturnType<typeof getWeb3Deployment> {
port: number
riverEnv: string
riverChainRpcUrl: string
}
Expand Down
6 changes: 5 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18281,12 +18281,16 @@ __metadata:
dependencies:
"@bufbuild/buf": ^1.32.0
"@bufbuild/protobuf": ^1.9.0
"@connectrpc/connect": ^1.4.0
"@connectrpc/connect-web": ^1.4.0
"@fastify/cors": ^9.0.1
"@river-build/generated": "workspace:^"
"@river-build/prettier-config": "workspace:^"
"@river-build/proto": "workspace:^"
"@river-build/sdk": "workspace:^"
"@river-build/web3": "workspace:^"
"@types/node": ^20.5.0
"@typescript-eslint/parser": ^7.14.1
dotenv: ^16.4.5
esbuild: ^0.21.5
ethers: ^5.7.2
Expand All @@ -18295,7 +18299,7 @@ __metadata:
rollup: ^4.18.1
ts-node: ^10.9.1
typescript: ^5.1.6
viem: ^1.18.2
zod: ^3.21.4
languageName: unknown
linkType: soft

Expand Down

0 comments on commit f4054fc

Please sign in to comment.