Skip to content

Commit 74d4767

Browse files
committed
add cancel feature
1 parent af312b1 commit 74d4767

File tree

4 files changed

+71
-17
lines changed

4 files changed

+71
-17
lines changed

apps/backend/app.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ def spawn_job(experiment_data):
6666
job = create_job_object(experiment_data)
6767
create_job(BATCH_API, job)
6868

69+
@flaskApp.post("/cancelExperiment")
70+
def cancel_experiment():
71+
"""The query to cancel an experiment"""
72+
data = request.get_json()
73+
job_name = data['jobName']
74+
# kill the job
75+
BATCH_API.delete_namespaced_job(job_name, "default", propagation_policy="Background")
76+
return Response(status=200)
77+
6978
@flaskApp.post("/uploadResults")
7079
def upload_results():
7180
json = request.get_json()

apps/backend/spawn_runner.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
def create_job_object(experiment_data):
1313
"""Function that creates the job object for the runner"""
1414
# Configure Pod template container
15-
job_name = "runner-" + str(time.time())
15+
job_name = "runner-" + experiment_data['experiment']['id']
16+
1617
job_command = ["python3", "runner.py", json.dumps(experiment_data)]
1718

1819
runner_body = get_yaml_file_body(RUNNER_PATH)

apps/frontend/app/components/flows/ViewExperiment/ExperimentListing.tsx

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
44
import { ExperimentData } from '../../../../lib/db_types';
55
import { MdEdit } from 'react-icons/md';
66
import Chart from './Chart';
7-
import { addShareLink, unfollowExperiment, updateExperimentNameById } from '../../../../lib/mongodb_funcs';
7+
import { addShareLink, unfollowExperiment, updateExperimentNameById, cancelExperimentById } from '../../../../lib/mongodb_funcs';
88
import toast from 'react-hot-toast';
99
import { useSession } from 'next-auth/react';
1010

@@ -248,13 +248,28 @@ export const ExperimentListing = ({ projectData: projectData, onCopyExperiment,
248248
</button> */}
249249
{
250250
project.creator == session?.user?.id! ?
251-
<button type="button"
252-
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
253-
onClick={() => {
254-
openDeleteModal();
255-
}}>
256-
Delete Experiment
257-
</button> :
251+
(
252+
project.finished ?
253+
<button type="button"
254+
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
255+
onClick={() => {
256+
openDeleteModal();
257+
}}>
258+
Delete Experiment
259+
</button>
260+
:
261+
<button type="button"
262+
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
263+
onClick={() => {
264+
toast.promise(cancelExperimentById(project.expId), {
265+
success: 'Cancelled experiment', error: 'Failed to cancel experiment', loading: 'Cancelling experiment...'
266+
});
267+
}}
268+
>
269+
Cancel Experiment
270+
</button>
271+
)
272+
:
258273
<button type="button"
259274
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
260275
onClick={() => {
@@ -267,12 +282,12 @@ export const ExperimentListing = ({ projectData: projectData, onCopyExperiment,
267282
</button>
268283
}
269284
{project.finished ?
270-
<button type="button"
271-
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
272-
onClick={openGraphModal}
273-
>
274-
See Graph
275-
</button> : null
285+
<button type="button"
286+
className='inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 xl:w-full'
287+
onClick={openGraphModal}
288+
>
289+
See Graph
290+
</button> : null
276291
}
277292
{
278293
project.creator == session?.user?.id! ?

apps/frontend/lib/mongodb_funcs.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,35 @@ export async function deleteDocumentById(expId: string) {
5555
return Promise.resolve();
5656
}
5757

58+
export async function cancelExperimentById(expId: string) {
59+
'use server';
60+
//Call the backend at the endpoint to cancel the experiment
61+
const BACKEND_PORT = process.env.BACKEND_PORT || '5050';
62+
const url = `http://glados-service-backend:${BACKEND_PORT}/cancelExperiment`;
63+
//Just post a json object with the experiment id
64+
const backendResponse = await fetch(url, {
65+
method: 'POST',
66+
headers: new Headers({
67+
'Content-Type': 'application/json',
68+
}),
69+
body: JSON.stringify({ jobName: 'runner-' + expId }),
70+
});
71+
72+
//Mark the experiment as completed
73+
const client = await clientPromise;
74+
const collection = client.db(DB_NAME).collection(COLLECTION_EXPERIMENTS);
75+
await collection
76+
.updateOne({ '_id': new ObjectId(expId) }, { $set: { 'finished': true } });
77+
78+
//If the backend returns a 200 status code, the experiment was successfully cancelled
79+
if (backendResponse.status === 200) {
80+
return Promise.resolve(true);
81+
} else {
82+
return Promise.resolve(false);
83+
}
84+
85+
}
86+
5887
export async function updateExperimentNameById(expId: string, newExpName: string) {
5988
'use server';
6089
const client = await clientPromise;
@@ -112,7 +141,7 @@ export async function getRecentFiles(userId: string) {
112141
return serializedFiles;
113142
}
114143

115-
export async function copyFile(fileID: string, userId: string){
144+
export async function copyFile(fileID: string, userId: string) {
116145
'use server';
117146
const client = await clientPromise;
118147
const db = client.db(DB_NAME);
@@ -240,4 +269,4 @@ export async function unfollowExperiment(expId: string, userId: string) {
240269
await collection.updateOne({ '_id': new ObjectId(expId) }, { $pull: { 'sharedUsers': userId as any } });
241270

242271
return Promise.resolve();
243-
}
272+
}

0 commit comments

Comments
 (0)