Skip to content

Commit

Permalink
Feature/save request (#842)
Browse files Browse the repository at this point in the history
* New route for saving and getting successfully dispatched requests

Signed-off-by: Aaron Chong <[email protected]>

* Announce failed to dispatch instead of create task

Signed-off-by: Aaron Chong <[email protected]>

* Generate api-client

Signed-off-by: Aaron Chong <[email protected]>

* Use api task request instead of custom ttm pydantic model

Signed-off-by: Aaron Chong <[email protected]>

* Revert alert text change

Signed-off-by: Aaron Chong <[email protected]>

---------

Signed-off-by: Aaron Chong <[email protected]>
(cherry picked from commit 52a7d14)
Signed-off-by: Aaron Chong <[email protected]>
  • Loading branch information
aaronchongth committed Nov 27, 2023
1 parent 9c2b590 commit 47afaec
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 2 deletions.
84 changes: 84 additions & 0 deletions packages/api-client/lib/openapi/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8375,6 +8375,47 @@ export const TasksApiAxiosParamCreator = function (configuration?: Configuration
options: localVarRequestOptions,
};
},
/**
*
* @summary Get Task Request
* @param {string} taskId task_id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getTaskRequestTasksTaskIdRequestGet: async (
taskId: string,
options: AxiosRequestConfig = {},
): Promise<RequestArgs> => {
// verify required parameter 'taskId' is not null or undefined
assertParamExists('getTaskRequestTasksTaskIdRequestGet', 'taskId', taskId);
const localVarPath = `/tasks/{task_id}/request`.replace(
`{${'task_id'}}`,
encodeURIComponent(String(taskId)),
);
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options };
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {
...localVarHeaderParameter,
...headersFromBaseOptions,
...options.headers,
};

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Available in socket.io
* @summary Get Task State
Expand Down Expand Up @@ -9353,6 +9394,23 @@ export const TasksApiFp = function (configuration?: Configuration) {
);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary Get Task Request
* @param {string} taskId task_id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getTaskRequestTasksTaskIdRequestGet(
taskId: string,
options?: AxiosRequestConfig,
): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<TaskRequest>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getTaskRequestTasksTaskIdRequestGet(
taskId,
options,
);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
* Available in socket.io
* @summary Get Task State
Expand Down Expand Up @@ -9811,6 +9869,18 @@ export const TasksApiFactory = function (
.getTaskLogTasksTaskIdLogGet(taskId, between, options)
.then((request) => request(axios, basePath));
},
/**
*
* @summary Get Task Request
* @param {string} taskId task_id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getTaskRequestTasksTaskIdRequestGet(taskId: string, options?: any): AxiosPromise<TaskRequest> {
return localVarFp
.getTaskRequestTasksTaskIdRequestGet(taskId, options)
.then((request) => request(axios, basePath));
},
/**
* Available in socket.io
* @summary Get Task State
Expand Down Expand Up @@ -10215,6 +10285,20 @@ export class TasksApi extends BaseAPI {
.then((request) => request(this.axios, this.basePath));
}

/**
*
* @summary Get Task Request
* @param {string} taskId task_id
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof TasksApi
*/
public getTaskRequestTasksTaskIdRequestGet(taskId: string, options?: AxiosRequestConfig) {
return TasksApiFp(this.configuration)
.getTaskRequestTasksTaskIdRequestGet(taskId, options)
.then((request) => request(this.axios, this.basePath));
}

/**
* Available in socket.io
* @summary Get Task State
Expand Down
2 changes: 1 addition & 1 deletion packages/api-client/lib/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { version as rmfModelVer } from 'rmf-models';

export const version = {
rmfModels: rmfModelVer,
rmfServer: '9c6122b74319a51ceff1ca27a493e1cbaf35aa42',
rmfServer: 'd6099b09fb9f13e06e029014f35a8ff1c4810abf',
openapiGenerator: '6.2.1',
};
30 changes: 30 additions & 0 deletions packages/api-client/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,36 @@ export default {
},
},
},
'/tasks/{task_id}/request': {
get: {
tags: ['Tasks'],
summary: 'Get Task Request',
operationId: 'get_task_request_tasks__task_id__request_get',
parameters: [
{
description: 'task_id',
required: true,
schema: { title: 'Task Id', type: 'string', description: 'task_id' },
name: 'task_id',
in: 'path',
},
],
responses: {
'200': {
description: 'Successful Response',
content: {
'application/json': { schema: { $ref: '#/components/schemas/TaskRequest' } },
},
},
'422': {
description: 'Validation Error',
content: {
'application/json': { schema: { $ref: '#/components/schemas/HTTPValidationError' } },
},
},
},
},
},
'/tasks': {
get: {
tags: ['Tasks'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
TaskEventLogPhasesLog,
TaskFavorite,
TaskFavoritePydantic,
TaskRequest,
TaskState,
)
from .user import *
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
from .log import LogMixin


class TaskRequest(Model):
id_ = CharField(255, pk=True, source_field="id")
request = JSONField()


class TaskState(Model):
id_ = CharField(255, pk=True, source_field="id")
data = JSONField()
Expand Down
13 changes: 13 additions & 0 deletions packages/api-server/api_server/repositories/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
Pagination,
Phases,
TaskEventLog,
TaskRequest,
TaskState,
User,
)
from api_server.models import tortoise_models as ttm
from api_server.models.rmf_api.log_entry import Tier
from api_server.models.rmf_api.task_state import Category, Id, Phase
from api_server.models.tortoise_models import TaskRequest as DbTaskRequest
from api_server.models.tortoise_models import TaskState as DbTaskState
from api_server.query import add_pagination
from api_server.rmf_io import task_events
Expand All @@ -30,6 +32,17 @@ class TaskRepository:
def __init__(self, user: User):
self.user = user

async def save_task_request(self, task_id: str, task_request: TaskRequest) -> None:
await DbTaskRequest.update_or_create(
{"request": task_request.json()}, id_=task_id
)

async def get_task_request(self, task_id: str) -> Optional[TaskRequest]:
result = await DbTaskRequest.get_or_none(id_=task_id)
if result is None:
return None
return TaskRequest(**result.request)

async def save_task_state(self, task_state: TaskState) -> None:
db_task_state = await DbTaskState.get_or_none(id_=task_state.booking.id)
if db_task_state is not None:
Expand Down
13 changes: 12 additions & 1 deletion packages/api-server/api_server/routes/tasks/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
router = FastIORouter(tags=["Tasks"])


@router.get("/{task_id}/request", response_model=mdl.TaskRequest)
async def get_task_request(
task_repo: TaskRepository = Depends(task_repo_dep),
task_id: str = Path(..., description="task_id"),
):
result = await task_repo.get_task_request(task_id)
if result is None:
raise HTTPException(status_code=404)
return result


@router.get("", response_model=List[mdl.TaskState])
async def query_task_states(
task_repo: TaskRepository = Depends(task_repo_dep),
Expand Down Expand Up @@ -145,10 +156,10 @@ async def post_dispatch_task(
)
if not resp.__root__.success:
return RawJSONResponse(resp.json(), 400)
new_state = cast(mdl.TaskDispatchResponseItem, resp.__root__).state
if task_warn_time is not None:
new_state.unix_millis_warn_time = task_warn_time
await task_repo.save_task_state(new_state)
await task_repo.save_task_request(new_state.booking.id, request.request)
return resp.__root__


Expand Down
13 changes: 13 additions & 0 deletions packages/api-server/api_server/routes/tasks/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,19 @@ def test_success(self):
self.assertEqual(200, resp.status_code, resp.content)
self.assertEqual(task_id, resp.json()["booking"]["id"])

def test_task_request_exist(self):
task_id = str(uuid4())
with patch.object(tasks_service(), "call") as mock:
mock.return_value = f'{{ "success": true, "state": {{ "booking": {{ "id": "{task_id}" }} }} }}'
resp = self.post_task_request()
self.assertEqual(200, resp.status_code, resp.content)

# check that the task request is in the database
resp = self.client.get(f"/tasks/{task_id}/request")
self.assertEqual(200, resp.status_code, resp.content)
self.assertEqual("test", resp.json()["category"])
self.assertEqual("description", resp.json()["description"])

def test_fail_with_multiple_errors(self):
# fails with multiple errors
with patch.object(tasks_service(), "call") as mock:
Expand Down

0 comments on commit 47afaec

Please sign in to comment.