@microfleet/core
Version:
Abstract microservice core
73 lines (61 loc) • 2.34 kB
text/typescript
import { Microfleet } from '../..'
import { promisify } from 'util'
import { strict as assert } from 'assert'
import { ArgumentError } from 'common-errors'
import _debug = require('debug')
import fs = require('fs')
import _glob = require('glob')
import path = require('path')
import { ERROR_NOT_HEALTHY, ERROR_NOT_STARTED } from './constants'
import Redis = require('ioredis')
const debug = _debug('mservice:lua')
const glob = promisify(_glob)
const readFile = promisify(fs.readFile)
/**
* Loads LUA script and defines it on the redis instance.
* @param dir - Directory to scan for LUA scripts to load.
* @param redis - Redis connector instance.
*/
export async function loadLuaScripts(
ctx: Microfleet,
dir: string | string[],
redis: Redis.Redis | Redis.Cluster
): Promise<void> {
// NOTE: this is a concious decision to use await serially
// so that it's easier to debug
// Operations that happen here are a one-off during script startup
// process and gains from reading files in parallel IMO aren't
// worth extra complexity
const locations = Array.isArray(dir) ? dir : [dir]
for (const location of locations) {
if (!path.isAbsolute(location)) {
throw new ArgumentError('config.scripts must be an absolute path')
}
debug('loading from %s', location)
const scripts = await glob('*.lua', { cwd: location })
for (const scriptName of scripts) {
const lua = await readFile(`${location}/${scriptName}`, 'utf8')
const name = path.basename(scriptName, '.lua')
debug('attaching %s', name)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (typeof redis[name] === 'undefined') {
// NOTICE: make sure that you pass number of keys as first arg when supplying function
redis.defineCommand(name, { lua })
} else {
ctx.log.warn('script %s already defined', name)
}
}
}
}
export function isStarted(service: Microfleet, RedisType: typeof Redis | Redis.ClusterStatic) {
return (): boolean => (
service.redis && (service.redis instanceof RedisType)
)
}
export async function hasConnection(this: Microfleet, hasRedis: () => boolean): Promise<boolean> {
assert(hasRedis(), ERROR_NOT_STARTED)
const ping = await this.redis.ping()
assert(ping, ERROR_NOT_HEALTHY)
return true
}