import { AsyncLocalStorage } from "async_hooks" ; import * as services from "@fluidframework/server-services" ; import * as core from "@fluidframework/server-services-core" ; import { Provider } from "nconf" ; import Redis from "ioredis" ; import winston from "winston" ; import * as historianServices from "./services" ; import { normalizePort } from "./utils" ; import { HistorianRunner } from "./runner" ; export class HistorianResources implements core . IResources { public webServerFactory : core . IWebServerFactory ; constructor ( public readonly config , public readonly port , public readonly riddler , public readonly throttler , public readonly cache ? , public readonly asyncLocalStorage ? ) { this . webServerFactory = new services . BasicWebServerFactory ( ) ; } public async dispose ( ) { return ; } } export class HistorianResourcesFactory implements core . IResourcesFactory < HistorianResources > { public async create ( config ) { const redisConfig = config . get ( "redis" ) ; const redisOptions = { host : redisConfig . host , port : redisConfig . port , password : redisConfig . pass , } ; if ( redisConfig . tls ) { redisOptions . tls = { servername : redisConfig . host , } ; } const redisParams = { expireAfterSeconds : redisConfig . keyExpireAfterSeconds as number | undefined , } ; const redisClient = new Redis ( redisOptions ) ; const disableGitCache = config . get ( "restGitService:disableGitCache" ) as boolean | undefined ; const gitCache = disableGitCache ? undefined : new historianServices . RedisCache ( redisClient , redisParams ) ; const tenantCache = new historianServices . RedisTenantCache ( redisClient , redisParams ) ; const riddlerEndpoint = config . get ( "riddler" ) ; const asyncLocalStorage = config . get ( "asyncLocalStorageInstance" ) ?. [ 0 ] ; const riddler = new historianServices . RiddlerService ( riddlerEndpoint , tenantCache , asyncLocalStorage ) ; const redisConfigForThrottling = config . get ( "redisForThrottling" ) ; const redisOptionsForThrottling = { host : redisConfigForThrottling . host , port : redisConfigForThrottling . port , password : redisConfigForThrottling . pass , } ; if ( redisConfigForThrottling . tls ) { redisOptionsForThrottling . tls = { servername : redisConfigForThrottling . host , } ; } const redisClientForThrottling = new Redis ( redisOptionsForThrottling ) ; const redisParamsForThrottling = { expireAfterSeconds : redisConfigForThrottling . keyExpireAfterSeconds as number | undefined , } ; const throttleMaxRequestsPerMs = config . get ( "throttling:maxRequestsPerMs" ) as number | undefined ; const throttleMaxRequestBurst = config . get ( "throttling:maxRequestBurst" ) as number | undefined ; const throttleMinCooldownIntervalInMs = config . get ( "throttling:minCooldownIntervalInMs" ) as number | undefined ; const minThrottleIntervalInMs = config . get ( "throttling:minThrottleIntervalInMs" ) as number | undefined ; const throttleStorageManager = new services . RedisThrottleStorageManager ( redisClientForThrottling , redisParamsForThrottling ) ; const throttlerHelper = new services . ThrottlerHelper ( throttleStorageManager , throttleMaxRequestsPerMs , throttleMaxRequestBurst , throttleMinCooldownIntervalInMs ) ; const throttler = new services . Throttler ( throttlerHelper , minThrottleIntervalInMs , winston ) ; const port = normalizePort ( process . env . PORT || "3000" ) ; return new HistorianResources ( config , port , riddler , throttler , gitCache , asyncLocalStorage ) ; } } export class HistorianRunnerFactory implements core . IRunnerFactory < HistorianResources > { public async create ( resources ) { return new HistorianRunner ( resources . webServerFactory , resources . config , resources . port , resources . riddler , resources . throttler , resources . cache , resources . asyncLocalStorage ) ; } }