Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
Author[]Andy Green <andy@warmcat.com> 2025-09-04 07:08 UTC
Committer[]Andy Green <andy@warmcat.com> 2025-09-04 16:09 UTC
Tree4c7fe3f7cbd1cb5fdd40f099a27d90339868c769   Raw Patch
 
feat: Add 'Rebuild last step' context menu option
feat: Add 'Rebuild last step' context menu option

Co-developed-by: Gemini 2.5 Pro
diff --git a/assets/sai.js b/assets/sai.js index 74a06f7..ee428f5 100644 --- a/assets/sai.js +++ b/assets/sai.js @@ -1920,6 +1920,18 @@ window.addEventListener("load", function() { } ]; + if (taskDiv.classList.contains("taskstate4") || + taskDiv.classList.contains("taskstate6")) + menuItems.splice(1, 0, { + label: "Rebuild last step", + callback: () => { + sai.send(JSON.stringify({ + schema: "com.warmcat.sai.taskrebuildlaststep", + uuid: taskUuid + })); + } + }); + createContextMenu(event, menuItems); } }); diff --git a/src/builder/b-metrics.c b/src/builder/b-metrics.c index 5532cfb..c2164b4 100644 --- a/src/builder/b-metrics.c +++ b/src/builder/b-metrics.c @@ -68,22 +68,6 @@ saib_get_free_ram_kib(void) statex.dwLength = sizeof(statex); GlobalMemoryStatusEx(&statex); return (unsigned int)(statex.ullAvailPhys / 1024); -#elif defined(__APPLE__) - int mib[2]; - size_t len; - uint64_t total_mem; - - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - len = sizeof(total_mem); - sysctl(mib, 2, &total_mem, &len, NULL, 0); - - return (unsigned int)(total_mem / 1024); -#elif defined(_WIN32) - MEMORYSTATUSEX statex; - statex.dwLength = sizeof(statex); - GlobalMemoryStatusEx(&statex); - return (unsigned int)(statex.ullTotalPhys / 1024); #else return 0; #endif @@ -108,6 +92,22 @@ saib_get_total_ram_kib(void) fclose(f); return total_kib; +#elif defined(__APPLE__) + int mib[2]; + size_t len; + uint64_t total_mem; + + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + len = sizeof(total_mem); + sysctl(mib, 2, &total_mem, &len, NULL, 0); + + return (unsigned int)(total_mem / 1024); +#elif defined(_WIN32) + MEMORYSTATUSEX statex; + statex.dwLength = sizeof(statex); + GlobalMemoryStatusEx(&statex); + return (unsigned int)(statex.ullTotalPhys / 1024); #else return 0; #endif diff --git a/src/server/s-private.h b/src/server/s-private.h index 5387e95..57d6b9c 100644 --- a/src/server/s-private.h +++ b/src/server/s-private.h @@ -289,6 +289,8 @@ sais_activity_cb(lws_sorted_usec_list_t *sul); sai_db_result_t sais_task_reset(struct vhd *vhd, const char *task_uuid, int from_rejection); +sai_db_result_t +sais_task_rebuild_last_step(struct vhd *vhd, const char *task_uuid); int sais_task_cancel(struct vhd *vhd, const char *task_uuid); diff --git a/src/server/s-task.c b/src/server/s-task.c index 383db95..3257566 100644 --- a/src/server/s-task.c +++ b/src/server/s-task.c @@ -83,6 +83,7 @@ sais_set_task_state(struct vhd *vhd, const char *builder_name, lws_dll2_owner_t o; int n, task_ostate; int ostate = state; + uint64_t started_orig = started; if (state == SAIES_STEP_SUCCESS) state = SAIES_BEING_BUILT; @@ -171,7 +172,8 @@ sais_set_task_state(struct vhd *vhd, const char *builder_name, builder_name ? ",builder_name='" : "", builder_name ? esc : "", builder_name ? "'" : "", - esc3, esc4, state == SAIES_WAITING ? ",build_step=0" : "", + esc3, esc4, state == SAIES_WAITING && started_orig == 1 ? + ",build_step=0" : "", esc2); if (sqlite3_exec((sqlite3 *)e->pdb, update, NULL, NULL, NULL) != SQLITE_OK) { @@ -911,6 +913,78 @@ sais_task_reset(struct vhd *vhd, const char *task_uuid, int from_rejection) return SAI_DB_RESULT_OK; } +sai_db_result_t +sais_task_rebuild_last_step(struct vhd *vhd, const char *task_uuid) +{ + char esc[96], cmd[256], event_uuid[33]; + sqlite3 *pdb = NULL; + lws_dll2_owner_t o; + struct lwsac *ac = NULL; + sai_task_t *task; + int ret; + + if (!task_uuid[0]) + return SAI_DB_RESULT_OK; + + lwsl_notice("%s: received request to rebuild last step of task %s\n", + __func__, task_uuid); + + sai_task_uuid_to_event_uuid(event_uuid, task_uuid); + + if (sais_event_db_ensure_open(vhd, event_uuid, 0, &pdb)) { + lwsl_err("%s: unable to open event-specific database\n", + __func__); + + return SAI_DB_RESULT_ERROR; + } + + lws_sql_purify(esc, task_uuid, sizeof(esc)); + lws_snprintf(cmd, sizeof(cmd), " and uuid='%s'", esc); + ret = lws_struct_sq3_deserialize(pdb, cmd, NULL, + lsm_schema_sq3_map_task, &o, &ac, 0, 1); + if (ret < 0 || !o.head) { + sais_event_db_close(vhd, &pdb); + lwsac_free(&ac); + return SAI_DB_RESULT_ERROR; + } + + task = lws_container_of(o.head, sai_task_t, list); + + if (task->build_step > 0) { + lws_snprintf(cmd, sizeof(cmd), + "update tasks set build_step=%d where uuid='%s'", + task->build_step - 1, esc); + + ret = sqlite3_exec(pdb, cmd, NULL, NULL, NULL); + if (ret != SQLITE_OK) { + sais_event_db_close(vhd, &pdb); + lwsac_free(&ac); + if (ret == SQLITE_BUSY) + return SAI_DB_RESULT_BUSY; + + lwsl_err("%s: %s: %s: fail\n", __func__, cmd, + sqlite3_errmsg(pdb)); + return SAI_DB_RESULT_ERROR; + } + } + + lwsac_free(&ac); + sais_event_db_close(vhd, &pdb); + + sais_set_task_state(vhd, NULL, NULL, task_uuid, SAIES_WAITING, 0, 0); + + sais_task_stop_on_builders(vhd, task_uuid); + + lwsl_err("%s: scheduling sul_central to find a new task\n", __func__); + lws_sul_schedule(vhd->context, 0, &vhd->sul_central, sais_central_cb, 1); + + sais_platforms_with_tasks_pending(vhd); + + lwsl_notice("%s: exiting OK\n", __func__); + + return SAI_DB_RESULT_OK; +} + /* * Look for any task on any event that needs building on platform_name, if found * the caller must take responsibility to free pss->a.ac diff --git a/src/server/s-websrv.c b/src/server/s-websrv.c index 58ac7d5..16e2fa8 100644 --- a/src/server/s-websrv.c +++ b/src/server/s-websrv.c @@ -77,6 +77,8 @@ static const lws_struct_map_t lsm_schema_json_map[] = { LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.taskreset"), LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, + /* shares struct */ "com.warmcat.sai.taskrebuildlaststep"), + LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.eventreset"), LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.eventdelete"), @@ -92,6 +94,7 @@ static const lws_struct_map_t lsm_schema_json_map[] = { enum { SAIS_WS_WEBSRV_RX_TASKRESET, + SAIS_WS_WEBSRV_RX_TASKREBUILDLASTSTEP, SAIS_WS_WEBSRV_RX_EVENTRESET, SAIS_WS_WEBSRV_RX_EVENTDELETE, SAIS_WS_WEBSRV_RX_TASKCANCEL, @@ -593,6 +596,18 @@ websrvss_ws_rx(void *userobj, const uint8_t *buf, size_t len, int flags) break; } + case SAIS_WS_WEBSRV_RX_TASKREBUILDLASTSTEP: + { + ei = (sai_browse_rx_evinfo_t *)a.dest; + if (sais_validate_id(ei->event_hash, SAI_TASKID_LEN)) + goto soft_error; + + lwsl_ss_warn(m->ss, "SAIS_WS_WEBSRV_RX_TASKREBUILDLASTSTEP: %s: received", ei->event_hash); + if (sais_task_rebuild_last_step(m->vhd, ei->event_hash)) + lwsl_ss_err(m->ss, "taskrebuildlaststep failed"); + break; + } + case SAIS_WS_WEBSRV_RX_EVENTRESET: { sai_db_result_t r; diff --git a/src/server/s-ws-builder.c b/src/server/s-ws-builder.c index 5e2d59b..0702730 100644 --- a/src/server/s-ws-builder.c +++ b/src/server/s-ws-builder.c @@ -712,8 +712,8 @@ bail: __func__, cb->name, rej->task_uuid[0] ? rej->task_uuid : "none"); -// if (rej->task_uuid[0]) -// sais_task_reset(vhd, rej->task_uuid, 1); + if (rej->task_uuid[0]) + sais_task_reset(vhd, rej->task_uuid, 1); lwsac_free(&pss->a.ac); break; diff --git a/src/web/w-ws-browser.c b/src/web/w-ws-browser.c index 0489d3d..44e3961 100644 --- a/src/web/w-ws-browser.c +++ b/src/web/w-ws-browser.c @@ -69,6 +69,8 @@ static const lws_struct_map_t lsm_schema_json_map_bwsrx[] = { LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.taskreset"), LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, + /* shares struct */ "com.warmcat.sai.taskrebuildlaststep"), + LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.eventreset"), LSM_SCHEMA (sai_browse_rx_evinfo_t, NULL, lsm_browser_taskreset, /* shares struct */ "com.warmcat.sai.eventdelete"), @@ -86,6 +88,7 @@ enum { SAIM_WS_BROWSER_RX_TASKINFO, SAIM_WS_BROWSER_RX_EVENTINFO, SAIM_WS_BROWSER_RX_TASKRESET, + SAIM_WS_BROWSER_RX_TASKREBUILDLASTSTEP, SAIM_WS_BROWSER_RX_EVENTRESET, SAIM_WS_BROWSER_RX_EVENTDELETE, SAIM_WS_BROWSER_RX_TASKCANCEL, @@ -507,6 +510,19 @@ saiw_ws_json_rx_browser(struct vhd *vhd, struct pss *pss, uint8_t *buf, saiw_websrv_queue_tx(vhd->h_ss_websrv, buf, bl, ss_flags); break; + case SAIM_WS_BROWSER_RX_TASKREBUILDLASTSTEP: + if (!sais_conn_auth(pss)) + goto auth_error; + + /* + * User is asking us to rebuild the last step of this task + */ + + ei = (sai_browse_rx_evinfo_t *)a.dest; + + saiw_websrv_queue_tx(vhd->h_ss_websrv, buf, bl, ss_flags); + break; + case SAIM_WS_BROWSER_RX_EVENTRESET: if (!sais_conn_auth(pss))
Page fetched 0s ago, creation time: 24ms (vhost etag hits: 0%, cache hits: 0%)