Skip to content

Commit

Permalink
Fix file upload bug (fixes #56) (#57)
Browse files Browse the repository at this point in the history
* Fix file upload bug (fixes #56)

* Promisified the upload controller

* test added

* python runner in repository deployment fixed
  • Loading branch information
HeeManSu authored Nov 5, 2024
1 parent 65063fa commit 8bce92f
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export class Application {
}

export const Applications: Record<string, Application> = {};

export const unzipPromises: Record<string, Promise<void>> = {};
6 changes: 5 additions & 1 deletion src/controller/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { hostname } from 'os';

import AppError from '../utils/appError';

import { Applications } from '../app';
import { Applications, unzipPromises } from '../app';
import { deployProcess } from '../utils/deploy';
import { installDependencies } from '../utils/install';
import { catchAsync } from './catch';
Expand All @@ -25,6 +25,8 @@ export const deploy = catchAsync(
next: NextFunction
) => {
try {
await unzipPromises[req.body.suffix];

const application = Applications[req.body.suffix];

// Check if the application exists and it is stored
Expand All @@ -37,6 +39,8 @@ export const deploy = catchAsync(

const resource = await application.resource;

// Wait for the unzipping to complete

await installDependencies(resource);

await deployProcess(resource);
Expand Down
3 changes: 2 additions & 1 deletion src/controller/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ const handleRunners = async (repoPath: string): Promise<string[]> => {
if (file === 'package.json') runners.push('nodejs');

if (stat.isDirectory()) {
await handleRunners(fullPath);
const subRunners = await handleRunners(fullPath);
runners.push(...subRunners);
}
}
return runners;
Expand Down
54 changes: 32 additions & 22 deletions src/controller/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from 'path';

import busboy from 'busboy';
import { NextFunction, Request, Response } from 'express';
import { Extract, ParseOptions } from 'unzipper';
import { Extract } from 'unzipper';

import { MetaCallJSON } from '@metacall/protocol/deployment';
import { Application, Applications, Resource } from '../app';
Expand Down Expand Up @@ -56,10 +56,10 @@ export const uploadPackage = (
jsons: []
};

let handled = false; // TODO: Promisify the whole controller
let handled = false;

const errorHandler = (error: AppError) => {
if (handled == false) {
if (handled === false) {
req.unpipe(bb);
next(error);
}
Expand Down Expand Up @@ -88,8 +88,8 @@ export const uploadPackage = (
const { mimeType, filename } = info;

if (
mimeType != 'application/x-zip-compressed' &&
mimeType != 'application/zip'
mimeType !== 'application/x-zip-compressed' &&
mimeType !== 'application/zip'
) {
return errorHandler(
new AppError('Please upload a zip file', 404)
Expand Down Expand Up @@ -147,7 +147,7 @@ export const uploadPackage = (

eventHandler('finish', () => {
if (resource.blob === undefined) {
throw Error('Invalid file upload, blob path is not defined');
throw new Error('Invalid file upload, blob path is not defined');
}

const deleteBlob = () => {
Expand Down Expand Up @@ -201,33 +201,43 @@ export const uploadPackage = (
}
);

const options: ParseOptions = { path: resource.path };
const unzipAndResolve = () => {
return new Promise<void>((resolve, reject) => {
fs.createReadStream(resource.blob as string)
.pipe(Extract({ path: resource.path }))
.on('close', () => {
deleteBlob();
resolve();
})
.on('error', error => {
deleteBlob();
deleteFolder();
reject(
new AppError(
`Failed to unzip the resource at: ${error.toString()}`,
500
)
);
});
});
};

fs.createReadStream(resource.blob)
.pipe(Extract(options))
.on('close', () => {
deleteBlob();
unzipAndResolve()
.then(() => {
resourceResolve(resource);
})
.on('error', error => {
deleteBlob();
deleteFolder();
const appError = new AppError(
`Failed to unzip the resource at: ${error.toString()}`,
500
);
errorHandler(appError);
resourceReject(appError);
.catch(error => {
resourceReject(error);
errorHandler(error);
});
});

eventHandler('close', () => {
if (handled == false) {
if (handled === false) {
res.status(201).json({
id: resource.id
});
}

handled = true;
});

Expand Down
51 changes: 39 additions & 12 deletions test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,6 @@ function test_nodejs_dependency_app() {
[[ $sum_response = 3 ]] || exit 1
}

# Run tests
run_tests "nodejs-base-app" test_nodejs_app
run_tests "python-base-app" test_python_base_app
run_tests "python-dependency-app" test_python_dependency_app
run_tests "nodejs-dependency-app" test_nodejs_dependency_app

echo "Integration tests for package deployment passed without errors."

Expand Down Expand Up @@ -308,20 +303,52 @@ function test_nodejs_dependency_app() {
echo "Node.js Dependency App tests passed"
}

echo "starting repository deployment tests"
# without Dependencies

#without Dependencies

#Test NodeJs app
# Test NodeJs app
test_deploy_from_repo "https://github.com/HeeManSu/nodejs-parameter-example" "nodejs-parameter-example" test_nodejs-parameter-example
# #Test Python app
# Test Python app
test_deploy_from_repo "https://github.com/HeeManSu/metacall-python-example" "metacall-python-example" test_python_time_app

# #With Dependencies
# With Dependencies

# # Test Python app
# Test Python app
test_deploy_from_repo "https://github.com/HeeManSu/python-dependency-metacall" "python-dependency-metacall" test_python_dependency_metacall
#Test NodeJs app
test_deploy_from_repo "https://github.com/HeeManSu/auth-middleware-metacall" "auth-middleware-metacall" test_nodejs_dependency_app

echo "Repository deployment tests completed."


# Simultaneous deployment tests
function test_simultaneous_deploy() {
echo "Testing simultaneous deployments..."
pids=()

# Run all tests simultaneously in background
run_tests "nodejs-base-app" test_nodejs_app &
pids+=($!)

run_tests "python-base-app" test_python_base_app &
pids+=($!)

run_tests "python-dependency-app" test_python_dependency_app &
pids+=($!)

run_tests "nodejs-dependency-app" test_nodejs_dependency_app &
pids+=($!)

for pid in "${pids[@]}"; do
if ! wait $pid; then
echo "Simultaneous deployment test failed - Test failed"
return 1
exit 1
fi
done

echo "Simultaneous deployment test passed - All tests passed"
return 0
}

echo "Testing simultaneous deployments..."
test_simultaneous_deploy

0 comments on commit 8bce92f

Please sign in to comment.