diff --git a/packages/app-service/.env.template b/packages/app-service/.env.template index 350a837659..8bdf67929d 100644 --- a/packages/app-service/.env.template +++ b/packages/app-service/.env.template @@ -2,3 +2,4 @@ DB_URI=mongodb://root:password123@localhost:27017/?authSource=admin&replicaSet=l SERVER_SALT=abcdefg1234567!@#$%^&sadfqwef&*^*#!@^ LOG_LEVEL=trace ENABLE_CLOUD_FUNCTION_LOG = always +FLAGS=--max_old_space_size=256 \ No newline at end of file diff --git a/packages/app-service/package-lock.json b/packages/app-service/package-lock.json index 720f4fda95..3eedd37f7c 100644 --- a/packages/app-service/package-lock.json +++ b/packages/app-service/package-lock.json @@ -5,7 +5,7 @@ "requires": true, "packages": { "": { - "version": "0.6.13", + "version": "0.6.14", "dependencies": { "alipay-sdk": "^3.1.7", "axios": "^0.21.1", @@ -17,6 +17,7 @@ "express": "^4.17.1", "fs-extra": "^9.1.0", "jsonwebtoken": "^8.5.1", + "laf-client-sdk": "^0.6.16", "lodash": "^4.17.21", "log4js": "^6.3.0", "mongodb": "^4.1.3", @@ -1734,6 +1735,15 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/laf-client-sdk": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/laf-client-sdk/-/laf-client-sdk-0.6.16.tgz", + "integrity": "sha512-4OUl3r6npjnbkTj+egj3R51Sr2uSrFKPBEGCv0iDW7n3eDdr2zjvnfPGOrjmtetxaO3nNijnmOf3UcQ2blhqeg==", + "dependencies": { + "axios": "^0.21.1", + "database-ql": "^0.6.2" + } + }, "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -4549,6 +4559,15 @@ "safe-buffer": "^5.0.1" } }, + "laf-client-sdk": { + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/laf-client-sdk/-/laf-client-sdk-0.6.16.tgz", + "integrity": "sha512-4OUl3r6npjnbkTj+egj3R51Sr2uSrFKPBEGCv0iDW7n3eDdr2zjvnfPGOrjmtetxaO3nNijnmOf3UcQ2blhqeg==", + "requires": { + "axios": "^0.21.1", + "database-ql": "^0.6.2" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", diff --git a/packages/app-service/package.json b/packages/app-service/package.json index 1cc54d9aa6..2858a53bfd 100644 --- a/packages/app-service/package.json +++ b/packages/app-service/package.json @@ -33,6 +33,7 @@ "express": "^4.17.1", "fs-extra": "^9.1.0", "jsonwebtoken": "^8.5.1", + "laf-client-sdk": "^0.6.16", "lodash": "^4.17.21", "log4js": "^6.3.0", "mongodb": "^4.1.3", diff --git a/packages/app-service/src/api/init.ts b/packages/app-service/src/api/init.ts new file mode 100644 index 0000000000..3c6a7985e2 --- /dev/null +++ b/packages/app-service/src/api/init.ts @@ -0,0 +1,99 @@ +import { ObjectId } from 'bson' +import fse = require('fs-extra') +import path = require('path') +import { Constants } from '../constants' +import { DatabaseAgent } from '../lib/database' +import { execSync } from 'child_process' + +/** + * 在 node_modules 中创建 云函数 sdk 包:@, 这个包是为了云函数IDE 加载类型提示文件而创建的,不可发布 + */ +export function createCloudFunctionDeclarationPackage() { + const source = path.resolve(__dirname, '../../dist') + const target = path.resolve(__dirname, '../../node_modules/@') + + fse.ensureDirSync(target) + fse.copySync(source, target) + + console.log(`copy success: ${source} => ${target}`) + + const packageJson = ` + { + "name": "@", + "version": "0.0.0" + } + ` + const pkgJsonPath = path.join(target, 'package.json') + fse.writeFileSync(pkgJsonPath, packageJson) + + console.log(`write success: ${pkgJsonPath}`) +} + +export function isCloudSdkPackageExists() { + const target = path.resolve(__dirname, '../../../node_modules/@') + const pkgJsonPath = path.join(target, 'package.json') + return fse.existsSync(pkgJsonPath) +} + +export function initCloudSdkPackage() { + if (!isCloudSdkPackageExists()) { + createCloudFunctionDeclarationPackage() + } +} + + +interface AppConfigItem { + _id: ObjectId + key: string + value: { + name: string, + version: string + }[] +} + +/** + * Get extra npm packages + * @returns + */ +export async function getExtraPackages() { + await DatabaseAgent.accessor.ready + const db = DatabaseAgent.db + const doc = await db.collection(Constants.config_collection) + .findOne({ key: 'packages' }) + + return doc?.value ?? [] +} + +/** + * Install packages + * @param packages + * @returns + */ +export function installPackages(packages: { name: string, version: string }[]) { + if (!packages?.length) { + return + } + + const names = packages + .map(pkg => { + return pkg.version ? `${pkg.name}@${pkg.version}` : `${pkg.name}` + }) + + const cmd_str = names.join(' ') + const r = execSync(`npm install ${cmd_str}`) + return r.toString() +} + +/** + * Check if node module exists + * @param moduleName + * @returns + */ +export function moduleExists(mod: string) { + try { + require.resolve(mod) + return true + } catch (_err) { + return false + } +} \ No newline at end of file diff --git a/packages/app-service/src/constants.ts b/packages/app-service/src/constants.ts index c0ab1ba361..bda85ba4e0 100644 --- a/packages/app-service/src/constants.ts +++ b/packages/app-service/src/constants.ts @@ -17,7 +17,12 @@ export const Constants = { /** * collection name of cloud functions' log */ - function_log_collection: "__function_logs" + function_log_collection: "__function_logs", + + /** + * collection name of application configuration + */ + config_collection: '__config__' } deepFreeze(Constants) \ No newline at end of file diff --git a/packages/app-service/src/index.ts b/packages/app-service/src/index.ts index ba9d9ecdef..42f7147956 100644 --- a/packages/app-service/src/index.ts +++ b/packages/app-service/src/index.ts @@ -11,7 +11,7 @@ import Config from './config' import { router } from './router/index' import { logger } from './lib/logger' import { generateUUID } from './lib/utils/rand' -import { initCloudSdkPackage } from './lib/utils/init' +import { initCloudSdkPackage } from './api/init' import { WebSocketAgent } from './lib/ws' initCloudSdkPackage() diff --git a/packages/app-service/src/init.ts b/packages/app-service/src/init.ts new file mode 100644 index 0000000000..0bbc35c16c --- /dev/null +++ b/packages/app-service/src/init.ts @@ -0,0 +1,35 @@ +import { getExtraPackages, initCloudSdkPackage, installPackages, moduleExists } from "./api/init" + + +async function main() { + const packages = await getExtraPackages() + if (!packages.length) { + console.log('no extra packages found') + return 0 + } + + console.log('packages loaded: ', packages) + + const not_exists = packages.filter(pkg => !moduleExists(pkg.name)) + if (!not_exists.length) { + console.log('no new packages to be installed') + return 0 + } + + try { + const res = installPackages(packages) + console.log(res) + + initCloudSdkPackage() + } catch (error) { + console.error(error) + return 1 + } + + return 0 +} + + +main().then(code => { + process.exit(code) +}) \ No newline at end of file diff --git a/packages/app-service/src/lib/utils/init.ts b/packages/app-service/src/lib/utils/init.ts deleted file mode 100644 index 37fd7c34c4..0000000000 --- a/packages/app-service/src/lib/utils/init.ts +++ /dev/null @@ -1,38 +0,0 @@ -import fse = require('fs-extra') -import path = require('path') - -/** - * 在 node_modules 中创建 云函数 sdk 包:@, 这个包是为了云函数IDE 加载类型提示文件而创建的,不可发布 - */ -export function createCloudFunctionDeclarationPackage() { - const source = path.resolve(__dirname, '../../../dist') - const target = path.resolve(__dirname, '../../../node_modules/@') - - fse.ensureDirSync(target) - fse.copySync(source, target) - - console.log(`copy success: ${source} => ${target}`) - - const packageJson = ` - { - "name": "@", - "version": "0.0.0" - } - ` - const pkgJsonPath = path.join(target, 'package.json') - fse.writeFileSync(pkgJsonPath, packageJson) - - console.log(`write success: ${pkgJsonPath}`) -} - -export function isCloudSdkPackageExists() { - const target = path.resolve(__dirname, '../../../node_modules/@') - const pkgJsonPath = path.join(target, 'package.json') - return fse.existsSync(pkgJsonPath) -} - -export function initCloudSdkPackage() { - if (!isCloudSdkPackageExists()) { - createCloudFunctionDeclarationPackage() - } -} \ No newline at end of file diff --git a/packages/app-service/start.sh b/packages/app-service/start.sh new file mode 100644 index 0000000000..89a0b9f53e --- /dev/null +++ b/packages/app-service/start.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +echo "****** init start ******" +node ./dist/init.js +echo "****** init end *******" + +# source .env +echo "****** start service: node $FLAGS ./dist/index.js *******" +exec node $FLAGS ./dist/index.js \ No newline at end of file diff --git a/packages/system-server/src/lib/service-driver/container.ts b/packages/system-server/src/lib/service-driver/container.ts index 20e3329f79..8b9989e13f 100644 --- a/packages/system-server/src/lib/service-driver/container.ts +++ b/packages/system-server/src/lib/service-driver/container.ts @@ -32,14 +32,16 @@ export class DockerContainerServiceDriver { const container = await this.docker.createContainer({ Image: imageName, - Cmd: ['node', `--max_old_space_size=${max_old_space_size}`, './dist/index.js'], + // Cmd: ['node', `--max_old_space_size=${max_old_space_size}`, './dist/index.js'], + Cmd: ['sh', '/app/start.sh'], name: `app_${app.appid}`, Env: [ `DB=${app.config.db_name}`, `DB_URI=${uri}`, `LOG_LEVEL=${logLevel}`, `ENABLE_CLOUD_FUNCTION_LOG=always`, - `SERVER_SECRET_SALT=${app.config.server_secret_salt}` + `SERVER_SECRET_SALT=${app.config.server_secret_salt}`, + `FLAGS=--max_old_space_size=${max_old_space_size}` ], ExposedPorts: { "8000/tcp": {}