feat(architecture): enforce lifecycle orchestration and layered component boundaries

This commit is contained in:
admin
2026-02-26 10:18:19 +08:00
parent 64c2c7d8c2
commit cf1fecb004
32 changed files with 1701 additions and 180 deletions

View File

@@ -8,6 +8,8 @@
#include "ble_printer_client.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "runtime_diagnostics.h"
#include "runtime_policy.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -16,6 +18,10 @@ static const char *TAG = "printer_protocol";
static bool request_status_sync(uint32_t timeout_ms) {
int64_t old_ms;
if (printer_protocol_is_stopping()) {
return false;
}
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(200)) != pdTRUE) {
return false;
}
@@ -29,6 +35,10 @@ static bool request_status_sync(uint32_t timeout_ms) {
int64_t deadline = esp_timer_get_time() / 1000 + timeout_ms;
while ((esp_timer_get_time() / 1000) < deadline) {
if (printer_protocol_is_stopping()) {
return false;
}
vTaskDelay(pdMS_TO_TICKS(20));
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(100)) != pdTRUE) {
@@ -111,6 +121,11 @@ static bool run_print_job(job_slot_t *job) {
(unsigned)job->height,
job->density);
if (printer_protocol_is_stopping()) {
snprintf(job->error, sizeof(job->error), "protocol stopping");
return false;
}
if (!ble_printer_client_is_connected()) {
snprintf(job->error, sizeof(job->error), "printer not connected");
ESP_LOGW(TAG, "job %u print aborted: %s", (unsigned)job->id, job->error);
@@ -160,6 +175,11 @@ static bool run_print_job(job_slot_t *job) {
(unsigned)hot_time);
for (size_t i = 0; i < total_chunks; ++i) {
if (printer_protocol_is_stopping()) {
snprintf(job->error, sizeof(job->error), "protocol stopping");
return false;
}
if (job->cancel_requested) {
snprintf(job->error, sizeof(job->error), "job canceled");
ESP_LOGW(TAG,
@@ -219,11 +239,21 @@ void printer_protocol_worker_task(void *arg) {
(void)arg;
while (true) {
uint32_t job_id;
if (xQueueReceive(s_job_queue, &job_id, portMAX_DELAY) != pdTRUE) {
if (printer_protocol_is_stopping()) {
break;
}
uint32_t job_id = 0;
if (xQueueReceive(s_job_queue,
&job_id,
pdMS_TO_TICKS(runtime_policy_printer_worker_queue_wait_ms())) != pdTRUE) {
continue;
}
if (job_id == PRINTER_JOB_SENTINEL_STOP || printer_protocol_is_stopping()) {
break;
}
if (xSemaphoreTake(s_mutex, pdMS_TO_TICKS(1000)) != pdTRUE) {
continue;
}
@@ -241,13 +271,14 @@ void printer_protocol_worker_task(void *arg) {
s_jobs[idx].finished_ms = esp_timer_get_time() / 1000;
}
xSemaphoreGive(s_mutex);
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_CANCELED, 1);
continue;
}
if (s_busy_refcnt != 0) {
xSemaphoreGive(s_mutex);
xQueueSendToFront(s_job_queue, &job_id, 0);
vTaskDelay(pdMS_TO_TICKS(20));
(void)xQueueSendToFront(s_job_queue, &job_id, 0);
vTaskDelay(pdMS_TO_TICKS(runtime_policy_printer_queue_retry_delay_ms()));
continue;
}
@@ -287,13 +318,16 @@ void printer_protocol_worker_task(void *arg) {
if (ok) {
s_jobs[idx].state = PRINT_JOB_STATE_SUCCESS;
s_jobs[idx].error[0] = '\0';
} else if (s_jobs[idx].cancel_requested) {
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_SUCCESS, 1);
} else if (s_jobs[idx].cancel_requested || printer_protocol_is_stopping()) {
s_jobs[idx].state = PRINT_JOB_STATE_CANCELED;
if (s_jobs[idx].error[0] == '\0') {
strlcpy(s_jobs[idx].error, "job canceled", sizeof(s_jobs[idx].error));
}
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_CANCELED, 1);
} else {
s_jobs[idx].state = PRINT_JOB_STATE_FAILED;
runtime_diag_counter_add(RUNTIME_DIAG_COUNTER_PRINTER_JOB_FAILED, 1);
}
int64_t duration_ms = 0;
@@ -317,6 +351,14 @@ void printer_protocol_worker_task(void *arg) {
free(s_jobs[idx].data);
s_jobs[idx].data = NULL;
runtime_diag_set_gauge(RUNTIME_DIAG_GAUGE_PRINTER_QUEUE_DEPTH,
(int32_t)uxQueueMessagesWaiting(s_job_queue));
xSemaphoreGive(s_mutex);
}
if (s_evt != NULL) {
xEventGroupSetBits(s_evt, EVT_WORKER_EXITED);
}
s_worker_task = NULL;
vTaskDelete(NULL);
}