Skip to content

Commit aa59c6c

Browse files
committed
fixes
1 parent ae4d320 commit aa59c6c

5 files changed

Lines changed: 53 additions & 7 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ _todo_update/
4242
botasaurus/botasaurus_storage.json
4343
bota/src/bota/package_storage.json
4444
FUTURE.md
45+
.history/

docs/docs/botasaurus-desktop/botasaurus-desktop-api/adding-domain-and-ssl.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ The process involves two main steps:
5353

5454
I use Porkbun because:
5555
- Unlike Cloudflare Domains, which is primarily a CDN provider, Porkbun specializes in domain registration. I want a specialist to manage my domains.
56-
- It offers automatic renewals.
56+
<!-- - It offers automatic renewals. -->
5757
- It sends multiple renewal reminders (45 days and 30 days before expiry), so I don't forget to renew my domains.
5858

5959
![Porkbun Renewal Emails](https://raw.githubusercontent.com/omkarcloud/botasaurus/master/images/domains/porkbun-renewal-emails.png)
6060

61-
Also, Porkbun's logo and branding are funny, nevertheless they provide a good experience and are [highly rated on Trustpilot.](https://www.trustpilot.com/review/porkbun.com)
61+
<!-- Also, Porkbun's logo and branding are funny, nevertheless they provide a good experience and are [highly rated on Trustpilot.](https://www.trustpilot.com/review/porkbun.com) -->
6262

6363
2. Next, log in to your domain registrar and create DNS **A records** pointing to your VM's IP address.
6464

js/botasaurus-desktop-api/src/index.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,15 @@ const api = new Api({ apiUrl: 'https://example.com' })`);
291291
}
292292
}
293293

294-
async getTasks({ page = 1, perPage, withResults = false, parentTaskId }: { page?: number; perPage?: number; withResults?: boolean; parentTaskId?: number } = { page: 1, withResults: true }): Promise<PaginatedResponse<Task>> {
294+
async getTasks({ page = 1, perPage, withResults = false, parentTaskId, status }: { page?: number; perPage?: number; withResults?: boolean; parentTaskId?: number; status?: string } = { page: 1, withResults: true }): Promise<PaginatedResponse<Task>> {
295295
/**
296296
* Fetches tasks from the server, with optional result inclusion, pagination, and filtering.
297297
*
298298
* @param page The page number for pagination.
299299
* @param perPage The number of tasks to return per page.
300300
* @param withResults Whether to include the task results in the response.
301301
* @param parentTaskId Filter tasks by parent task ID.
302+
* @param status Filter tasks by status (pending, in_progress, completed, failed, aborted).
302303
* @return A dictionary containing the task results and pagination information.
303304
*/
304305
const url = this._makeApiUrl("tasks");
@@ -308,6 +309,7 @@ const api = new Api({ apiUrl: 'https://example.com' })`);
308309
if (page !== undefined && page !== null) params.page = page;
309310
if (perPage !== undefined && perPage !== null) params.per_page = perPage;
310311
if (parentTaskId !== undefined && parentTaskId !== null) params.parent_task_id = parentTaskId;
312+
if (status !== undefined && status !== null) params.status = status;
311313
try {
312314
const response = await axios.get(url, { params });
313315

@@ -333,6 +335,10 @@ const api = new Api({ apiUrl: 'https://example.com' })`);
333335
}
334336
}
335337

338+
async getFailedTasks({ page = 1, perPage, withResults = false, parentTaskId }: { page?: number; perPage?: number; withResults?: boolean; parentTaskId?: number } = { page: 1, withResults: true }): Promise<PaginatedResponse<Task>> {
339+
return this.getTasks({ page, perPage, withResults, parentTaskId, status: 'failed' });
340+
}
341+
336342
async getTask(taskId: number): Promise<Task> {
337343
/**
338344
* Retrieves a specific task by ID.
@@ -572,4 +578,26 @@ const api = new Api({ apiUrl: 'https://example.com' })`);
572578
throw error;
573579
}
574580
}
581+
582+
async retryTasks({ taskIds }: { taskIds: number[] }): Promise<OkResponse> {
583+
/**
584+
* Bulk retries failed tasks.
585+
*
586+
* @param taskIds A list of task IDs to be retried.
587+
* @return A success message.
588+
*/
589+
const url = this._makeApiUrl("tasks/bulk-retry");
590+
const payload = { task_ids: taskIds };
591+
try {
592+
const response = await axios.post(url, payload);
593+
594+
this._writeJson("retry_tasks", response.data);
595+
return response.data;
596+
} catch (error) {
597+
if (axios.isAxiosError(error)) {
598+
raiseIfBadException(error.response as AxiosResponse);
599+
}
600+
throw error;
601+
}
602+
}
575603
}

js/botasaurus-server-js/src/api-config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
deleteSingleTask,
1111
bulkAbortTasks,
1212
bulkDeleteTasks,
13+
bulkRetryTasks,
1314
getAppProps,
1415
isAnyTaskUpdated,
1516
isTaskUpdated,
@@ -605,6 +606,12 @@ export function buildApp(
605606
return result;
606607
});
607608

609+
app.post(`${apiBasePath}/tasks/bulk-retry`, async (request, _) => {
610+
const jsonData = request.body;
611+
const result = await bulkRetryTasks(jsonData);
612+
return result;
613+
});
614+
608615
app.get(`${apiBasePath}/ui/app-props`, getAppProps);
609616

610617
app.post(

js/botasaurus-server-js/src/routes-db-logic.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,13 @@ async function queryTasks(
9999
page?: any,
100100
per_page?: any,
101101
serializer: (task: any, withResults: boolean) => Promise<any> = serializeTask,
102-
parent_task_id?: number | null
102+
parent_task_id?: number | null,
103+
status?: string | null
103104
): Promise<any> {
104105
const projectionFields = createProjection(ets);
105-
const queryFilter = isNotNullish(parent_task_id) ? { parent_task_id } : {};
106+
const queryFilter: Record<string, any> = {};
107+
if (isNotNullish(parent_task_id)) queryFilter.parent_task_id = parent_task_id;
108+
if (status) queryFilter.status = status;
106109
const total_count = await wrapDbOperationInPromise((cb:any) => db.count(queryFilter, cb));
107110

108111
if (isNullish(per_page)) {
@@ -689,7 +692,14 @@ async function executeGetTasks(queryParams: Record<string, any>): Promise<any> {
689692
}
690693
}
691694

692-
return queryTasks(getEts(), withResults, page, per_page, serializeTask, parent_task_id);
695+
const status = queryParams.status;
696+
if (isNotNullish(status) && ![TaskStatus.PENDING, TaskStatus.IN_PROGRESS, TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.ABORTED].includes(status)) {
697+
throw new JsonHTTPResponseWithMessage(
698+
`Invalid 'status' parameter value: "${status}". It must be one of: pending, in_progress, completed, failed, aborted.`
699+
);
700+
}
701+
702+
return queryTasks(getEts(), withResults, page, per_page, serializeTask, parent_task_id, status);
693703
}
694704

695705
function isValidAllTasks(tasks: any[]): boolean {
@@ -1066,7 +1076,7 @@ function convertUnicodeDictToAsciiDictInPlace(inputList: any[]): any[] {
10661076
// Only abort tasks that are in PENDING or IN_PROGRESS status
10671077
const abortableStatuses: string[] = [TaskStatus.PENDING, TaskStatus.IN_PROGRESS];
10681078
if (!abortableStatuses.includes(status)) {
1069-
// return;
1079+
return;
10701080
}
10711081

10721082
let fn: (() => Promise<void>) | null = null;

0 commit comments

Comments
 (0)