Skip to content

Commit

Permalink
feat(cu): require cu mode for /result, /results, /cron, /state endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
TillaTheHun0 committed Dec 23, 2024
1 parent 7eab3ca commit bf69887
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 11 deletions.
1 change: 1 addition & 0 deletions servers/cu/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const server = pipeP(
*/
const server = app.listen({ port: config.port, host: '0.0.0.0' }, () => {
logger(`Server is running on http://localhost:${config.port}`)
logger(`Server in unit mode: "${config.UNIT_MODE}"`)
})

const memMonitor = setInterval(async () => {
Expand Down
34 changes: 31 additions & 3 deletions servers/cu/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const DEFAULT_PROCESS_WASM_MODULE_FORMATS = [
*/
const serverConfigSchema = domainConfigSchema.extend({
MODE: z.enum(['development', 'production']),
/**
* Whether the unit is operating as a Compute Unit
* or Read Unit. Defaults to 'cu'.
*/
UNIT_MODE: z.enum(['cu', 'ru']),
port: positiveIntSchema,
ENABLE_METRICS_ENDPOINT: z.preprocess((val) => !!val, z.boolean())
})
Expand All @@ -51,13 +56,32 @@ const serverConfigSchema = domainConfigSchema.extend({
*/
/* eslint-disable no-throw-literal */

const preprocessUnitMode = (envConfig) => {
const { UNIT_MODE } = envConfig

if (UNIT_MODE === 'cu') return envConfig

/**
* A Read Unit's primary concern is serving dry-runs,
* and so does not create checkpoints and does not cache evaluation
* results to be served later.
*/
return {
...envConfig,
DISABLE_PROCESS_EVALUATION_CACHE: true,
DISABLE_PROCESS_CHECKPOINT_CREATION: true,
DISABLE_PROCESS_FILE_CHECKPOINT_CREATION: true,
PROCESS_MEMORY_CACHE_CHECKPOINT_INTERVAL: 0
}
}

/**
* If the WALLET is defined, then do nothing.
*
* Otherwise, check whether the WALLET_FILE env var is defined and load it contents
* as WALLET
*/
export const preprocessWallet = (envConfig) => {
const preprocessWallet = (envConfig) => {
const { WALLET, WALLET_FILE, ...theRestOfTheConfig } = envConfig

// WALLET takes precendent. nothing to do here
Expand All @@ -83,7 +107,7 @@ export const preprocessWallet = (envConfig) => {
const preprocessedServerConfigSchema = z.preprocess(
(envConfig, zodRefinementContext) => {
try {
return pipe(preprocessWallet, preprocessUrls)(envConfig)
return pipe(preprocessUnitMode, preprocessWallet, preprocessUrls)(envConfig)
} catch (message) {
zodRefinementContext.addIssue({ code: ZodIssueCode.custom, message })
}
Expand All @@ -100,6 +124,7 @@ const preprocessedServerConfigSchema = z.preprocess(
const CONFIG_ENVS = {
development: {
MODE,
UNIT_MODE: process.env.UNIT_MODE || 'cu',
DEFAULT_LOG_LEVEL: process.env.DEFAULT_LOG_LEVEL || 'debug',
LOG_CONFIG_PATH: process.env.LOG_CONFIG_PATH || '.loglevel',
MODULE_MODE: process.env.MODULE_MODE,
Expand All @@ -117,6 +142,7 @@ const CONFIG_ENVS = {
PROCESS_CHECKPOINT_CREATION_THROTTLE: process.env.PROCESS_CHECKPOINT_CREATION_THROTTLE || ms('30m'),
DISABLE_PROCESS_CHECKPOINT_CREATION: process.env.DISABLE_PROCESS_CHECKPOINT_CREATION !== 'false',
DISABLE_PROCESS_FILE_CHECKPOINT_CREATION: process.env.DISABLE_PROCESS_FILE_CHECKPOINT_CREATION !== 'false',
DISABLE_PROCESS_EVALUATION_CACHE: process.env.DISABLE_PROCESS_EVALUATION_CACHE,
/**
* EAGER_CHECKPOINT_ACCUMULATED_GAS_THRESHOLD: Amount of gas for 2 hours of continuous compute (300_000_000_000_000)
* This was calculated by creating a process built to do continuous compute. After 2 hours, this process used
Expand Down Expand Up @@ -149,6 +175,7 @@ const CONFIG_ENVS = {
},
production: {
MODE,
UNIT_MODE: process.env.UNIT_MODE || 'cu',
DEFAULT_LOG_LEVEL: process.env.DEFAULT_LOG_LEVEL || 'debug',
LOG_CONFIG_PATH: process.env.LOG_CONFIG_PATH || '.loglevel',
MODULE_MODE: process.env.MODULE_MODE,
Expand All @@ -164,8 +191,9 @@ const CONFIG_ENVS = {
WALLET_FILE: process.env.WALLET_FILE,
MEM_MONITOR_INTERVAL: process.env.MEM_MONITOR_INTERVAL || ms('30s'),
PROCESS_CHECKPOINT_CREATION_THROTTLE: process.env.PROCESS_CHECKPOINT_CREATION_THROTTLE || ms('30m'),
DISABLE_PROCESS_CHECKPOINT_CREATION: process.env.DISABLE_PROCESS_CHECKPOINT_CREATION !== 'false', // TODO: disabled by default for now. Enable by default later
DISABLE_PROCESS_CHECKPOINT_CREATION: process.env.DISABLE_PROCESS_CHECKPOINT_CREATION !== 'false',
DISABLE_PROCESS_FILE_CHECKPOINT_CREATION: process.env.DISABLE_PROCESS_FILE_CHECKPOINT_CREATION !== 'false',
DISABLE_PROCESS_EVALUATION_CACHE: process.env.DISABLE_PROCESS_EVALUATION_CACHE,
/**
* EAGER_CHECKPOINT_ACCUMULATED_GAS_THRESHOLD: Amount of gas for 2 hours of continuous compute (300_000_000_000_000)
* This was calculated by creating a process built to do continuous compute by adding and clearing a table.
Expand Down
4 changes: 3 additions & 1 deletion servers/cu/src/routes/cron.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { always, compose, identity } from 'ramda'
import { z } from 'zod'

import { withMetrics, withMiddleware, withProcessRestrictionFromPath } from './middleware/index.js'
import { withCuMode } from './middleware/withCuMode.js'

/**
* TODO: could be moved into a route utils or middleware
Expand Down Expand Up @@ -37,8 +38,9 @@ export const withCronRoutes = app => {
'/cron/:processId',
compose(
withMiddleware,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
withCuMode,
withProcessRestrictionFromPath,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
always(async (req, res) => {
const {
params: { processId },
Expand Down
1 change: 1 addition & 0 deletions servers/cu/src/routes/middleware/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { withDomain } from './withDomain.js'

export * from './withProcessRestriction.js'
export * from './withMetrics.js'
export * from './withCuMode.js'

/**
* A convenience method that composes common middleware needed on most routes,
Expand Down
12 changes: 12 additions & 0 deletions servers/cu/src/routes/middleware/withCuMode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { config } from '../../config.js'

const withUnitMode = (mode) => (handler) => (req, res, next) => {
const { UNIT_MODE } = config

if (UNIT_MODE !== mode) return res.status(404).send('Not Found')

return handler(req, res, next)
}

export const withCuMode = withUnitMode('cu')
export const withRuMode = withUnitMode('ru')
5 changes: 3 additions & 2 deletions servers/cu/src/routes/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { compose } from 'ramda'
import { z } from 'zod'

import { busyIn } from '../domain/utils.js'
import { withMetrics, withMiddleware, withProcessRestrictionFromQuery } from './middleware/index.js'
import { withMetrics, withMiddleware, withProcessRestrictionFromQuery, withCuMode } from './middleware/index.js'
import { withInMemoryCache } from './middleware/withInMemoryCache.js'

const inputSchema = z.object({
Expand All @@ -15,8 +15,9 @@ export const withResultRoutes = app => {
'/result/:messageTxId',
compose(
withMiddleware,
withMetrics({ tracesFrom: (req) => ({ process_id: req.query['process-id'] }) }),
withCuMode,
withProcessRestrictionFromQuery,
withMetrics({ tracesFrom: (req) => ({ process_id: req.query['process-id'] }) }),
withInMemoryCache({
keyer: (req) => {
const { params: { messageTxId } } = req
Expand Down
7 changes: 4 additions & 3 deletions servers/cu/src/routes/results.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { always, compose, identity } from 'ramda'

import { withMetrics, withMiddleware, withProcessRestrictionFromPath } from './middleware/index.js'
import { z } from 'zod'

import { withMetrics, withMiddleware, withProcessRestrictionFromPath, withCuMode } from './middleware/index.js'

/**
* TODO: could be moved into a route utils or middleware
*
Expand Down Expand Up @@ -47,8 +47,9 @@ export const withResultsRoutes = app => {
'/results/:processId',
compose(
withMiddleware,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
withCuMode,
withProcessRestrictionFromPath,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
always(async (req, res) => {
const {
params: { processId },
Expand Down
5 changes: 3 additions & 2 deletions servers/cu/src/routes/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { always, compose } from 'ramda'
import { z } from 'zod'

import { arrayBufferFromMaybeView, busyIn } from '../domain/utils.js'
import { withMetrics, withMiddleware, withProcessRestrictionFromPath } from './middleware/index.js'
import { withMetrics, withMiddleware, withProcessRestrictionFromPath, withCuMode } from './middleware/index.js'

const inputSchema = z.object({
processId: z.string().min(1, 'an ao process id is required'),
Expand All @@ -15,8 +15,9 @@ export const withStateRoutes = (app) => {
'/state/:processId',
compose(
withMiddleware,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
withCuMode,
withProcessRestrictionFromPath,
withMetrics({ tracesFrom: (req) => ({ process_id: req.params.processId }) }),
always(async (req, res) => {
const {
params: { processId },
Expand Down

0 comments on commit bf69887

Please sign in to comment.