Skip to content

Commit a9b1dea

Browse files
committed
Solve issues
1 parent 1b8b77c commit a9b1dea

10 files changed

+158
-118
lines changed

README.md

+13-13
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,45 @@
22

33
Reimplementation of MetaCall FaaS platform written in TypeScript. This project requires MetaCall installed in order to run it. For more information about installation: https://github.com/metacall/install
44

5-
### Development:
5+
### Development
6+
67
```sh
78
npm install
89
npm start
910
```
1011

11-
### About Project :
12+
### About Project
1213

13-
MetaCall organization has its own cloud platform known as [MetaCall Hub](https://metacall.io/), a production-ready and high-performance FaaS/Cloud platform where you can deploy services, web apps, and lambdas in seconds. However, the ```Real``` version of MetaCall FaaS is commercialized and requires a plan to deploy your polyglot applications, which can be found [Here](https://metacall.io/pricing/).
14+
MetaCall organization has its own cloud platform known as [MetaCall Hub](https://metacall.io/), a production-ready and high-performance FaaS/Cloud platform where you can deploy services, web apps, and lambdas in seconds. However, the `Real` version of MetaCall FaaS is commercialized and requires a plan to deploy your polyglot applications, which can be found [Here](https://metacall.io/pricing/).
1415

15-
When referring to the ```Real``` version of MetaCall FaaS, it should be noted that this refers to the commercialized FaaS cloud service, whereas ```Local``` refers to the mimic version.
16+
When referring to the `Real` version of MetaCall FaaS, it should be noted that this refers to the commercialized FaaS cloud service, whereas `Local` refers to the mimic version.
1617

17-
Soon, we realized that many contributors joining the community needed an paid account on the ```Real FaaS``` for testing their polyglot applications. To remove this barrier, we proposed a project that would mimic the ```Real FaaS```.
18+
Soon, we realized that many contributors joining the community needed an paid account on the `Real FaaS` for testing their polyglot applications. To remove this barrier, we proposed a project that would mimic the `Real FaaS`.
1819

1920
With this project, developers can now use it to deploy and test their polyglot applications (built using [MetaCall Core](https://github.com/metacall/core)), web apps, and lambdas. The process is simple:
2021

21-
- Step 1 : Spin up the "Local FaaS" by running the following command:
22+
- Step 1 : Spin up the "Local FaaS" by running the following command:
2223

2324
```sh
2425
cd faas
2526
npm start
2627
```
2728

28-
- Step 2 : Install the [metacall-deploy](https://www.npmjs.com/package/@metacall/deploy) NPM package, and wire the ```--dev``` flag with the ```metacall-deploy``` command in your application directory using the following command:
29+
- Step 2 : Install the [metacall-deploy](https://www.npmjs.com/package/@metacall/deploy) NPM package, and wire the `--dev` flag with the `metacall-deploy` command in your application directory using the following command:
2930

3031
```sh
3132
cd move-to-application-directory
3233
metacall-deploy --dev
3334
```
3435

35-
### Things that need to be implemented:
36+
### Things that need to be implemented
3637

37-
- In order to mimic the "Real FaaS", we need to create all the API endpoints that the "Real FaaS" supports, which can be found listed [Here](https://github.com/metacall/protocol/blob/master/src/protocol.ts).
38+
- In order to mimic the "Real FaaS", we need to create all the API endpoints that the "Real FaaS" supports, which can be found listed [Here](https://github.com/metacall/protocol/blob/master/src/protocol.ts).
3839

3940
### Important Note
4041

41-
- This project is still under development and there is one extra thing you need to install before running this project and its [MetaCall Core](https://github.com/metacall/core/blob/develop/docs/README.md#41-installation).
42-
43-
- This project is developed using [MetaCall Core] itself in order to provide polyglot support, we are using its [Node Port](https://github.com/metacall/core/tree/develop/source/ports/node_port) of this library to use all the functions and methods ```MetaCall Core C API``` provides.
42+
- This project is still under development and there is one extra thing you need to install before running this project and its [MetaCall Core](https://github.com/metacall/core/blob/develop/docs/README.md#41-installation).
4443

45-
- Also, [Here](https://github.com/metacall/faas/blob/master/types/metacall.d.ts) are all the functions of ```MetaCall Core``` we are using.
44+
- This project is developed using [MetaCall Core] itself in order to provide polyglot support, we are using its [Node Port](https://github.com/metacall/core/tree/develop/source/ports/node_port) of this library to use all the functions and methods `MetaCall Core C API` provides.
4645

46+
- Also, [Here](https://github.com/metacall/faas/blob/master/types/metacall.d.ts) are all the functions of `MetaCall Core` we are using.

package-lock.json

+9-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
"description": "Reimplementation of MetaCall FaaS platform written in TypeScript.",
55
"main": "dist/server.js",
66
"scripts": {
7-
"test": "npm run --silent build && mocha dist/test",
8-
"unit": "npm run --silent test -- --ignore **/integration**",
9-
"prepublishOnly": "npm run --silent build",
10-
"build": "npm run --silent lint && tsc",
7+
"test": "npm run build && mocha dist/test",
8+
"unit": "npm run test -- --ignore **/integration**",
9+
"prepublishOnly": "npm run build",
10+
"build": "npm run lint && tsc",
1111
"lint": "eslint . --max-warnings=0 --ignore-pattern dist",
1212
"fix": "eslint . --max-warnings=0 --ignore-pattern dist --fix",
1313
"start": "npm run build && metacall dist/server.js"
@@ -89,6 +89,7 @@
8989
"@types/busboy": "^1.3.0",
9090
"@types/express": "^4.17.15",
9191
"@types/git-clone": "^0.2.0",
92+
"@types/node": "^14.14.7",
9293
"@types/unzipper": "^0.10.5",
9394
"@typescript-eslint/eslint-plugin": "^4.7.0",
9495
"@typescript-eslint/parser": "^4.7.0",
@@ -100,4 +101,4 @@
100101
"prettier": "^2.1.2",
101102
"typescript": "^4.3.2"
102103
}
103-
}
104+
}

src/api.ts

+21-17
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@ import deployDeleteController from './controller/delete';
88
import uploadController from './controller/upload';
99

1010
import {
11+
CurrentUploadedFile,
12+
ProtocolMessageType,
13+
WorkerMessage,
14+
WorkerMessageUnknown,
1115
allApplications,
12-
childProcessResponse,
1316
childProcesses,
1417
currentFile,
1518
deleteBody,
1619
deployBody,
1720
fetchBranchListBody,
18-
fetchFilesFromRepoBody,
19-
protocol
21+
fetchFilesFromRepoBody
2022
} from './constants';
2123

2224
import AppError from './utils/appError';
@@ -68,19 +70,19 @@ export const callFnByName = (
6870
let errorCame = false;
6971

7072
childProcesses[app].send({
71-
type: protocol.c,
72-
fn: {
73+
type: ProtocolMessageType.Invoke,
74+
data: {
7375
name,
7476
args
7577
}
7678
});
7779

78-
childProcesses[app].on('message', (data: childProcessResponse) => {
80+
childProcesses[app].on('message', (message: WorkerMessageUnknown) => {
7981
if (!responseSent) {
8082
// Check if response has already been sent
81-
if (data.type === protocol.r) {
83+
if (message.type === ProtocolMessageType.InvokeResult) {
8284
responseSent = true; // Set flag to true to indicate response has been sent
83-
return res.send(JSON.stringify(data.data));
85+
return res.send(JSON.stringify(message.data));
8486
} else {
8587
errorCame = true;
8688
}
@@ -141,7 +143,7 @@ export const fetchFilesFromRepo = catchAsync(
141143
await ensureFolderExists(appsDir);
142144

143145
try {
144-
deleteRepoFolderIfExist(appsDir, url);
146+
await deleteRepoFolderIfExist(appsDir, url);
145147
} catch (err) {
146148
next(
147149
new AppError(
@@ -196,7 +198,7 @@ export const fetchFileList = catchAsync(
196198
await ensureFolderExists(appsDir);
197199

198200
try {
199-
deleteRepoFolderIfExist(appsDir, req.body.url);
201+
await deleteRepoFolderIfExist(appsDir, req.body.url);
200202
} catch (err) {
201203
next(
202204
new AppError(
@@ -242,19 +244,21 @@ export const deploy = catchAsync(
242244
});
243245

244246
proc.send({
245-
type: protocol.l,
246-
currentFile
247+
type: ProtocolMessageType.Load,
248+
data: currentFile
247249
});
248250

249251
logProcessOutput(proc.stdout, proc.pid, currentFile.id);
250252
logProcessOutput(proc.stderr, proc.pid, currentFile.id);
251253

252-
proc.on('message', (data: childProcessResponse) => {
253-
if (data.type === protocol.g) {
254-
if (isIAllApps(data.data)) {
255-
const appName = Object.keys(data.data)[0];
254+
proc.on('message', (payload: WorkerMessageUnknown) => {
255+
if (payload.type === ProtocolMessageType.MetaData) {
256+
const message =
257+
payload as WorkerMessage<CurrentUploadedFile>;
258+
if (isIAllApps(message.data)) {
259+
const appName = Object.keys(message.data)[0];
256260
childProcesses[appName] = proc;
257-
allApplications[appName] = data.data[appName];
261+
allApplications[appName] = message.data[appName];
258262
}
259263
}
260264
});

src/app.ts

-11
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import express, { NextFunction, Request, Response } from 'express';
55
import * as api from './api';
66
import { allApplications } from './constants';
77
import AppError from './utils/appError';
8-
import { findJsonFilesRecursively } from './utils/autoDeploy';
9-
import { appsDirectory } from './utils/config';
108
import globalErrorHandler from './utils/errorHandler';
119

1210
const app = express();
@@ -44,15 +42,6 @@ app.all('*', (req: Request, res: Response, next: NextFunction) => {
4442
next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404));
4543
});
4644

47-
const appsDir = appsDirectory();
48-
findJsonFilesRecursively(appsDir)
49-
.then(() => {
50-
console.log('Previously deployed apllications deployed successfully');
51-
})
52-
.catch(error => {
53-
console.error('Error while re-deploying applications', error);
54-
});
55-
5645
app.use(globalErrorHandler);
5746

5847
export default app;

src/constants.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { DeployStatus, MetaCallJSON } from '@metacall/protocol/deployment';
22
import { ChildProcess } from 'child_process';
33

4-
export interface currentUploadedFile {
4+
export interface CurrentUploadedFile {
55
id: string;
66
type?: string;
77
jsons: MetaCallJSON[];
88
runners?: string[];
99
path: string;
1010
}
1111

12-
export const currentFile: currentUploadedFile = {
12+
export const currentFile: CurrentUploadedFile = {
1313
id: '',
1414
type: '',
1515
jsons: [],
@@ -100,21 +100,23 @@ export type IAllApps = Record<string, IAppWithFunctions>;
100100

101101
export const allApplications: IAllApps = {};
102102

103-
export const protocol = {
104-
i: 'installDependencies',
105-
l: 'loadFunctions',
106-
g: 'getApplicationMetadata',
107-
c: 'callFunction',
108-
r: 'functionInvokeResult'
109-
};
103+
export enum ProtocolMessageType {
104+
Install = 'InstallDependencies',
105+
Load = 'LoadFunctions',
106+
MetaData = 'GetApplicationMetadata',
107+
Invoke = 'CallFunction',
108+
InvokeResult = 'FunctionInvokeResult'
109+
}
110110

111111
export const childProcesses: { [key: string]: ChildProcess } = {};
112112

113-
export interface childProcessResponse {
114-
type: keyof typeof protocol;
115-
data: unknown;
113+
export interface WorkerMessage<T> {
114+
type: ProtocolMessageType;
115+
data: T;
116116
}
117117

118+
export type WorkerMessageUnknown = WorkerMessage<unknown>;
119+
118120
export interface InspectObject {
119121
[key: string]: Array<{ name: string }>;
120122
}

src/server.ts

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
import * as dotenv from 'dotenv';
22

33
import app from './app';
4+
import { findJsonFilesRecursively } from './utils/autoDeploy';
5+
import { appsDirectory } from './utils/config';
6+
import { ensureFolderExists } from './utils/utils';
47

5-
dotenv.config();
8+
// Initialize the FaaS
9+
void (async (): Promise<void> => {
10+
try {
11+
dotenv.config();
612

7-
const port = process.env.PORT || 9000;
13+
const appsDir = appsDirectory();
814

9-
app.listen(port, () => {
10-
console.log(`Server is running on the port ${port}`);
11-
});
15+
await ensureFolderExists(appsDir);
16+
17+
await findJsonFilesRecursively(appsDir);
18+
19+
console.log('Previously deployed apllications deployed successfully');
20+
21+
const port = process.env.PORT || 9000;
22+
23+
app.listen(port, () => {
24+
console.log(`Server is running on the port ${port}`);
25+
});
26+
} catch (e) {
27+
console.error('Error while re-deploying applications: ', e);
28+
}
29+
})();

src/utils/autoDeploy.ts

+20-12
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import { spawn } from 'child_process';
33
import * as fs from 'fs';
44
import * as path from 'path';
55
import {
6+
CurrentUploadedFile,
7+
IAppWithFunctions,
8+
ProtocolMessageType,
9+
WorkerMessage,
10+
WorkerMessageUnknown,
611
allApplications,
7-
childProcessResponse,
812
childProcesses,
9-
currentFile,
10-
protocol
13+
currentFile
1114
} from '../constants';
1215
import { isIAllApps, logProcessOutput } from './utils';
1316

@@ -31,20 +34,25 @@ export const findJsonFilesRecursively = async (
3134
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
3235
});
3336

34-
proc.send({
35-
type: protocol.l,
36-
currentFile
37-
});
37+
const message: WorkerMessage<CurrentUploadedFile> = {
38+
type: ProtocolMessageType.Load,
39+
data: currentFile
40+
};
41+
42+
proc.send(message);
3843

3944
logProcessOutput(proc.stdout, proc.pid, currentFile.id);
4045
logProcessOutput(proc.stderr, proc.pid, currentFile.id);
4146

42-
proc.on('message', (data: childProcessResponse) => {
43-
if (data.type === protocol.g) {
44-
if (isIAllApps(data.data)) {
45-
const appName = Object.keys(data.data)[0];
47+
proc.on('message', (payload: WorkerMessageUnknown) => {
48+
if (payload.type === ProtocolMessageType.MetaData) {
49+
const message = payload as WorkerMessage<
50+
Record<string, IAppWithFunctions>
51+
>;
52+
if (isIAllApps(message.data)) {
53+
const appName = Object.keys(message.data)[0];
4654
childProcesses[appName] = proc;
47-
allApplications[appName] = data.data[appName];
55+
allApplications[appName] = message.data[appName];
4856
}
4957
}
5058
});

0 commit comments

Comments
 (0)