@sincpro/mobile 0.4.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/adapters/JsonSerializer.adapter.d.ts +1 -1
- package/dist/adapters/JsonSerializer.adapter.js +2 -2
- package/dist/adapters/ReceiptExporter.adapter.js +10 -2
- package/dist/adapters/repositories/database_table.repository.d.ts +3 -2
- package/dist/adapters/repositories/database_table.repository.js +1 -1
- package/dist/adapters/repositories/document.repository.d.ts +81 -0
- package/dist/adapters/repositories/document.repository.js +653 -0
- package/dist/adapters/repositories/domain_event.repository.d.ts +17 -17
- package/dist/adapters/repositories/domain_event.repository.js +25 -31
- package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +10 -10
- package/dist/adapters/repositories/domain_event_dead_letter.repository.js +14 -13
- package/dist/adapters/repositories/event_row.d.ts +13 -0
- package/dist/adapters/repositories/event_row.js +22 -0
- package/dist/adapters/repositories/sqlite_document_store.d.ts +33 -0
- package/dist/adapters/repositories/sqlite_document_store.js +201 -0
- package/dist/domain/connectivity/events.d.ts +5 -5
- package/dist/domain/connectivity/events.js +3 -3
- package/dist/domain/database/criteria.d.ts +19 -0
- package/dist/domain/database/criteria.js +36 -0
- package/dist/domain/database/criteria_clock.d.ts +8 -0
- package/dist/domain/database/criteria_clock.js +305 -0
- package/dist/domain/database/criteria_sql.d.ts +61 -0
- package/dist/domain/database/criteria_sql.js +476 -0
- package/dist/domain/database/database.d.ts +1 -0
- package/dist/domain/database/index.d.ts +3 -1
- package/dist/domain/database/index.js +3 -1
- package/dist/domain/database/migration_plan.d.ts +14 -0
- package/dist/domain/database/migration_plan.js +44 -0
- package/dist/domain/entity/change_tracking.d.ts +21 -0
- package/dist/domain/entity/change_tracking.js +71 -0
- package/dist/domain/entity/checks.d.ts +8 -0
- package/dist/domain/entity/checks.js +82 -0
- package/dist/domain/entity/entity.d.ts +39 -32
- package/dist/domain/entity/entity.js +94 -105
- package/dist/domain/entity/entity_collection.d.ts +15 -30
- package/dist/domain/entity/entity_collection.js +30 -121
- package/dist/domain/entity/index.d.ts +5 -0
- package/dist/domain/entity/index.js +5 -0
- package/dist/domain/entity/reconcile.d.ts +7 -0
- package/dist/domain/entity/reconcile.js +12 -0
- package/dist/domain/entity/relations.d.ts +27 -0
- package/dist/domain/entity/relations.js +69 -0
- package/dist/domain/entity/remote_sync.d.ts +4 -0
- package/dist/domain/entity/remote_sync.js +19 -0
- package/dist/domain/entity/values.d.ts +6 -0
- package/dist/domain/entity/values.js +13 -0
- package/dist/domain/events/catalog.d.ts +29 -0
- package/dist/domain/{events.js → events/catalog.js} +7 -11
- package/dist/domain/events/chain.d.ts +5 -0
- package/dist/domain/events/chain.js +6 -0
- package/dist/domain/{event_sourcing → events}/domain_event.d.ts +20 -22
- package/dist/domain/events/domain_event.js +227 -0
- package/dist/domain/events/index.d.ts +8 -0
- package/dist/domain/events/index.js +8 -0
- package/dist/domain/events/integration_event.d.ts +103 -0
- package/dist/domain/events/integration_event.js +72 -0
- package/dist/domain/events/label.d.ts +2 -0
- package/dist/domain/events/label.js +26 -0
- package/dist/domain/index.d.ts +0 -1
- package/dist/domain/index.js +0 -1
- package/dist/domain/print/events.d.ts +8 -4
- package/dist/domain/print/events.js +9 -4
- package/dist/domain/repositories/document_store.d.ts +33 -0
- package/dist/domain/repositories/document_store.js +5 -0
- package/dist/domain/repositories/hooks.d.ts +23 -0
- package/dist/domain/repositories/hooks.js +32 -0
- package/dist/domain/repositories/index.d.ts +4 -0
- package/dist/domain/repositories/index.js +4 -0
- package/dist/domain/{database → repositories}/repository.d.ts +9 -3
- package/dist/domain/settings.d.ts +4 -1
- package/dist/domain/settings.js +3 -0
- package/dist/domain/webview/events.d.ts +2 -2
- package/dist/domain/webview/events.js +2 -2
- package/dist/entrypoints/db/migrations.js +10 -10
- package/dist/entrypoints/queue/QueueProcessor.d.ts +1 -1
- package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +2 -2
- package/dist/entrypoints/queue/activateDomain.subscriber.js +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.d.ts +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.js +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.js +2 -2
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +1 -1
- package/dist/entrypoints/ui/AppShell.js +2 -2
- package/dist/entrypoints/ui/common_provider.d.ts +1 -13
- package/dist/entrypoints/ui/common_provider.js +4 -133
- package/dist/entrypoints/ui/domain_switcher.d.ts +2 -2
- package/dist/event_driven/index.d.ts +1 -0
- package/dist/event_driven/index.js +1 -0
- package/dist/{domain/event_sourcing/event_handler.d.ts → event_driven/subscriber.d.ts} +1 -1
- package/dist/exceptions.d.ts +21 -0
- package/dist/exceptions.js +30 -0
- package/dist/framework/base_module.d.ts +1 -1
- package/dist/framework/createApp.d.ts +3 -3
- package/dist/framework/domain_module.d.ts +1 -1
- package/dist/framework/feature.d.ts +26 -0
- package/dist/framework/feature.js +36 -0
- package/dist/framework/kernel.d.ts +1 -1
- package/dist/framework/kernel.js +17 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/infrastructure/database/connector.d.ts +2 -0
- package/dist/infrastructure/database/connector.js +22 -0
- package/dist/infrastructure/database/index.d.ts +1 -0
- package/dist/infrastructure/database/index.js +1 -0
- package/dist/infrastructure/database/schema.d.ts +9 -0
- package/dist/infrastructure/database/schema.js +61 -0
- package/dist/infrastructure/database/utils.d.ts +2 -0
- package/dist/infrastructure/database/utils.js +12 -4
- package/dist/infrastructure/event_chain.d.ts +6 -0
- package/dist/infrastructure/event_chain.js +25 -0
- package/dist/infrastructure/interceptor/intercept.d.ts +7 -2
- package/dist/infrastructure/interceptor/intercept.js +5 -2
- package/dist/infrastructure/telemetry/tracing/tracing_hooks.d.ts +9 -6
- package/dist/infrastructure/telemetry/tracing/tracing_hooks.js +61 -35
- package/dist/infrastructure/ui/UIEventBus.d.ts +3 -1
- package/dist/infrastructure/ui/UIEventBus.js +8 -1
- package/dist/infrastructure/ui/activity.d.ts +37 -0
- package/dist/infrastructure/ui/activity.js +84 -0
- package/dist/infrastructure/workers/CronWorker.d.ts +6 -4
- package/dist/infrastructure/workers/CronWorker.js +24 -18
- package/dist/infrastructure/workers/EventBus.d.ts +9 -5
- package/dist/infrastructure/workers/EventBus.js +68 -33
- package/dist/services/bluetooth.service.js +16 -14
- package/dist/services/dead_letter_queue.service.d.ts +7 -7
- package/dist/services/dead_letter_queue.service.js +0 -2
- package/dist/services/event.service.d.ts +3 -3
- package/dist/services/event.service.js +1 -1
- package/dist/services/network.service.d.ts +1 -1
- package/dist/services/network.service.js +17 -15
- package/dist/services/printer.service.d.ts +1 -1
- package/dist/services/printer.service.js +50 -44
- package/dist/tools/utils/date.js +4 -3
- package/dist/tools/utils/monetary.d.ts +6 -3
- package/dist/tools/utils/monetary.js +33 -21
- package/dist/tools/utils/serializer.d.ts +1 -1
- package/dist/tools/utils/serializer.js +32 -35
- package/dist/ui/activity/DeviceNotices.d.ts +1 -0
- package/dist/ui/activity/DeviceNotices.js +29 -0
- package/dist/ui/activity/ProcessToast.d.ts +2 -0
- package/dist/ui/activity/ProcessToast.js +71 -0
- package/dist/ui/{components/molecules → activity}/ProcessToastProvider.d.ts +1 -1
- package/dist/ui/activity/index.d.ts +4 -0
- package/dist/ui/activity/index.js +4 -0
- package/dist/ui/activity/useActivity.d.ts +9 -0
- package/dist/ui/activity/useActivity.js +48 -0
- package/dist/ui/components/atoms/DebugBanner.d.ts +1 -1
- package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.d.ts +1 -1
- package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.js +8 -2
- package/dist/ui/components/molecules/DeadLetterErrorBlock.d.ts +1 -1
- package/dist/ui/components/molecules/EventTimelineItem.d.ts +3 -3
- package/dist/ui/components/molecules/EventTimelineItem.js +1 -1
- package/dist/ui/components/molecules/GeoPermissionCard.d.ts +1 -1
- package/dist/ui/components/molecules/TimeZoneSelector.d.ts +1 -1
- package/dist/ui/components/molecules/TimeZoneSelectorModal.d.ts +1 -1
- package/dist/ui/components/molecules/TimeZoneSelectorModal.js +5 -3
- package/dist/ui/components/molecules/index.d.ts +1 -2
- package/dist/ui/components/molecules/index.js +1 -2
- package/dist/ui/components/organisms/BluetoothPrinterSelector.d.ts +1 -1
- package/dist/ui/components/organisms/BluetoothPrinterSelector.js +3 -0
- package/dist/ui/components/organisms/DatabaseInfoRow.d.ts +1 -1
- package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +5 -4
- package/dist/ui/components/organisms/EventRow.d.ts +4 -4
- package/dist/ui/components/organisms/EventRow.js +1 -1
- package/dist/ui/components/organisms/InjectableWebView.d.ts +2 -2
- package/dist/ui/components/organisms/InjectableWebView.js +6 -3
- package/dist/ui/components/organisms/Receipt.d.ts +2 -1
- package/dist/ui/components/organisms/TableInfoInfoRow.d.ts +1 -1
- package/dist/ui/screens/database/database.context.d.ts +2 -2
- package/dist/ui/screens/database/database.context.js +9 -18
- package/dist/ui/screens/database/database.json_detail.d.ts +1 -1
- package/dist/ui/screens/database/database.list.d.ts +1 -1
- package/dist/ui/screens/database/database.table_rows.d.ts +1 -1
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +7 -7
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.d.ts +1 -1
- package/dist/ui/screens/events/events.context.d.ts +6 -6
- package/dist/ui/screens/events/events.context.js +20 -25
- package/dist/ui/screens/events/events.list.d.ts +1 -1
- package/package.json +51 -40
- package/dist/domain/event_sourcing/domain_event.js +0 -164
- package/dist/domain/event_sourcing/event.d.ts +0 -25
- package/dist/domain/event_sourcing/event.js +0 -25
- package/dist/domain/event_sourcing/index.d.ts +0 -2
- package/dist/domain/event_sourcing/index.js +0 -2
- package/dist/domain/events.d.ts +0 -33
- package/dist/infrastructure/ui/ToastHost.d.ts +0 -6
- package/dist/infrastructure/ui/ToastHost.js +0 -28
- package/dist/infrastructure/ui/events.d.ts +0 -1
- package/dist/infrastructure/ui/events.js +0 -1
- package/dist/ui/components/molecules/ProcessToast.d.ts +0 -8
- package/dist/ui/components/molecules/ProcessToast.js +0 -52
- /package/dist/domain/{repositories.d.ts → repositories/catalog.d.ts} +0 -0
- /package/dist/domain/{repositories.js → repositories/catalog.js} +0 -0
- /package/dist/domain/{database → repositories}/repository.js +0 -0
- /package/dist/{domain/event_sourcing/event_handler.js → event_driven/subscriber.js} +0 -0
- /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loggerCronJobs } from "../../infrastructure/logger";
|
|
2
|
-
import {
|
|
2
|
+
import { publishActivity } from "../../infrastructure/ui/activity";
|
|
3
3
|
import * as BackgroundTask from "expo-background-task";
|
|
4
4
|
import * as TaskManager from "expo-task-manager";
|
|
5
5
|
export class CronWorker {
|
|
@@ -12,20 +12,20 @@ export class CronWorker {
|
|
|
12
12
|
registrationError;
|
|
13
13
|
requiresAuth;
|
|
14
14
|
label;
|
|
15
|
-
|
|
15
|
+
ui;
|
|
16
16
|
constructor(taskName, job, intervalMin = 15, opts = {}) {
|
|
17
17
|
this.taskName = taskName;
|
|
18
18
|
this.job = job;
|
|
19
19
|
this.intervalMin = intervalMin;
|
|
20
20
|
this.requiresAuth = opts.requiresAuth ?? false;
|
|
21
21
|
this.label = opts.label;
|
|
22
|
-
this.
|
|
22
|
+
this.ui = opts.ui ?? false;
|
|
23
23
|
}
|
|
24
24
|
configure(opts) {
|
|
25
25
|
if (opts.label !== undefined)
|
|
26
26
|
this.label = opts.label;
|
|
27
|
-
if (opts.
|
|
28
|
-
this.
|
|
27
|
+
if (opts.ui !== undefined)
|
|
28
|
+
this.ui = opts.ui;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Registers a task with a specified interval and execution logic.
|
|
@@ -45,14 +45,10 @@ export class CronWorker {
|
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
47
|
TaskManager.defineTask(this.taskName, async () => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
catch (e) {
|
|
53
|
-
loggerCronJobs.warn(`${this.taskName} error:`, e);
|
|
54
|
-
return BackgroundTask.BackgroundTaskResult.Failed;
|
|
55
|
-
}
|
|
48
|
+
const ok = await this.runWithEvents(this.job);
|
|
49
|
+
return ok
|
|
50
|
+
? BackgroundTask.BackgroundTaskResult.Success
|
|
51
|
+
: BackgroundTask.BackgroundTaskResult.Failed;
|
|
56
52
|
});
|
|
57
53
|
await BackgroundTask.registerTaskAsync(this.taskName, {
|
|
58
54
|
minimumInterval: this.intervalMin,
|
|
@@ -116,25 +112,35 @@ export class CronWorker {
|
|
|
116
112
|
async runWithEvents(job) {
|
|
117
113
|
this.isExecuting = true;
|
|
118
114
|
const startTime = Date.now();
|
|
119
|
-
|
|
120
|
-
UIEventBus.emit("CRON_START", { task: this.taskName, label: this.label });
|
|
121
|
-
}
|
|
115
|
+
this.publish("running");
|
|
122
116
|
try {
|
|
123
117
|
await Promise.resolve(job());
|
|
124
118
|
const duration = Date.now() - startTime;
|
|
125
119
|
loggerCronJobs.debug(`${this.taskName} completed successfully in ${duration}ms`);
|
|
120
|
+
this.publish("succeeded");
|
|
121
|
+
return true;
|
|
126
122
|
}
|
|
127
123
|
catch (e) {
|
|
128
124
|
const duration = Date.now() - startTime;
|
|
129
125
|
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
130
126
|
loggerCronJobs.error(`${this.taskName} failed after ${duration}ms with error: ${errorMessage}`);
|
|
127
|
+
this.publish("failed", errorMessage);
|
|
128
|
+
return false;
|
|
131
129
|
}
|
|
132
130
|
finally {
|
|
133
131
|
this.isExecuting = false;
|
|
134
|
-
if (this.showToast)
|
|
135
|
-
UIEventBus.emit("CRON_END", { task: this.taskName });
|
|
136
132
|
}
|
|
137
133
|
}
|
|
134
|
+
publish(status, detail) {
|
|
135
|
+
publishActivity({
|
|
136
|
+
channel: "cron",
|
|
137
|
+
name: this.taskName,
|
|
138
|
+
label: this.label ?? this.taskName,
|
|
139
|
+
detail,
|
|
140
|
+
status,
|
|
141
|
+
ui: this.ui,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
138
144
|
/**
|
|
139
145
|
* Waits for current job execution to complete (if any).
|
|
140
146
|
* Timeout after 10 seconds to prevent infinite wait.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EventName, type IntegrationEvent } from "../../domain/events";
|
|
2
|
+
import { Subscriber } from "../../event_driven";
|
|
2
3
|
export declare const PROCESS_WORKER_MAX_ATTEMPTS = 1;
|
|
3
4
|
export { EventName };
|
|
4
5
|
export declare class EventBus {
|
|
@@ -8,6 +9,7 @@ export declare class EventBus {
|
|
|
8
9
|
private static readonly BACKOFF_MULTIPLIER;
|
|
9
10
|
private static subscribers;
|
|
10
11
|
private static isDraining;
|
|
12
|
+
private static connectivityReady;
|
|
11
13
|
private static intervalId;
|
|
12
14
|
private static internetConnected;
|
|
13
15
|
private static consecutiveFailures;
|
|
@@ -25,12 +27,12 @@ export declare class EventBus {
|
|
|
25
27
|
*/
|
|
26
28
|
static waitForIdle(): Promise<void>;
|
|
27
29
|
/**
|
|
28
|
-
*
|
|
30
|
+
* Logs the start and publishes a running activity when a subscriber exists.
|
|
29
31
|
* Returns false if no subscribers (caller should return early).
|
|
30
32
|
*/
|
|
31
33
|
private static preProcess;
|
|
32
34
|
/**
|
|
33
|
-
* Handles persistence, emits event
|
|
35
|
+
* Handles persistence, emits the event for screens, publishes the activity, logs result.
|
|
34
36
|
* If errors is empty -> success, otherwise -> failure + dead letter + throws.
|
|
35
37
|
* @throws Error if there are any errors
|
|
36
38
|
*/
|
|
@@ -47,13 +49,14 @@ export declare class EventBus {
|
|
|
47
49
|
/**
|
|
48
50
|
* Publishes a DomainEvent asynchronously - enqueues for later processing.
|
|
49
51
|
*/
|
|
50
|
-
static
|
|
52
|
+
static schedule(): void;
|
|
53
|
+
static publish(event: IntegrationEvent): Promise<void>;
|
|
51
54
|
/**
|
|
52
55
|
* Publishes a DomainEvent synchronously - executes all subscribers immediately.
|
|
53
56
|
* Saves event to DB for traceability. Moves to dead letter on failure.
|
|
54
57
|
* @throws Error if any subscriber fails or no subscribers registered
|
|
55
58
|
*/
|
|
56
|
-
static publishSync(event:
|
|
59
|
+
static publishSync(event: IntegrationEvent): Promise<void>;
|
|
57
60
|
/**
|
|
58
61
|
* Processes all pending DomainEvents from the domain_events table.
|
|
59
62
|
* Executes ALL subscribers registered for each event.
|
|
@@ -64,4 +67,5 @@ export declare class EventBus {
|
|
|
64
67
|
* Clears the event queue (domain_events table).
|
|
65
68
|
*/
|
|
66
69
|
static clearQueue(): Promise<void>;
|
|
70
|
+
private static publishQueue;
|
|
67
71
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { DomainEventRepository } from "../../adapters/repositories/domain_event.repository";
|
|
2
2
|
import { DomainEventDeadLetterRepository } from "../../adapters/repositories/domain_event_dead_letter.repository";
|
|
3
|
-
import { InternetIsDownEvent, InternetIsUpEvent
|
|
4
|
-
import { DomainNetworkError } from "../../exceptions";
|
|
3
|
+
import { InternetIsDownEvent, InternetIsUpEvent } from "../../domain/events";
|
|
4
|
+
import { DomainNetworkError, RepeatableFailure } from "../../exceptions";
|
|
5
|
+
import { runWithChain } from "../../infrastructure/event_chain";
|
|
5
6
|
import { loggerQueueProcessor } from "../../infrastructure/logger";
|
|
7
|
+
import { declaresUi, publishActivity } from "../../infrastructure/ui/activity";
|
|
6
8
|
import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
|
|
7
9
|
export const PROCESS_WORKER_MAX_ATTEMPTS = 1;
|
|
8
10
|
export class EventBus {
|
|
@@ -12,11 +14,15 @@ export class EventBus {
|
|
|
12
14
|
static BACKOFF_MULTIPLIER = 1.5;
|
|
13
15
|
static subscribers = new Map();
|
|
14
16
|
static isDraining = false;
|
|
17
|
+
static connectivityReady = false;
|
|
15
18
|
static intervalId = null;
|
|
16
19
|
static internetConnected = true;
|
|
17
20
|
static consecutiveFailures = 0;
|
|
18
21
|
static currentInterval = EventBus.INTERVAL_MS;
|
|
19
22
|
static initConnectivityListeners() {
|
|
23
|
+
if (this.connectivityReady)
|
|
24
|
+
return;
|
|
25
|
+
this.connectivityReady = true;
|
|
20
26
|
UIEventBus.on(InternetIsDownEvent.name, () => {
|
|
21
27
|
this.internetConnected = false;
|
|
22
28
|
this.consecutiveFailures++;
|
|
@@ -102,27 +108,22 @@ export class EventBus {
|
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
/**
|
|
105
|
-
*
|
|
111
|
+
* Logs the start and publishes a running activity when a subscriber exists.
|
|
106
112
|
* Returns false if no subscribers (caller should return early).
|
|
107
113
|
*/
|
|
108
114
|
static preProcess(event) {
|
|
109
115
|
const hasSubscribers = this.subscribers.has(event.name);
|
|
110
116
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - STARTED`);
|
|
111
117
|
loggerQueueProcessor.debug(`EVENT=${event.name} uuid=${event.uuid} payload=${event.asJSON()}`);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
event: event.name,
|
|
115
|
-
label: event.label,
|
|
116
|
-
attempts: event.attempts,
|
|
117
|
-
attemptLimit: EventBus.MAX_ATTEMPTS,
|
|
118
|
-
});
|
|
118
|
+
if (hasSubscribers)
|
|
119
|
+
this.publishQueue(event, "running");
|
|
119
120
|
if (!hasSubscribers) {
|
|
120
121
|
loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] - No subscribers registered`);
|
|
121
122
|
}
|
|
122
123
|
return hasSubscribers;
|
|
123
124
|
}
|
|
124
125
|
/**
|
|
125
|
-
* Handles persistence, emits event
|
|
126
|
+
* Handles persistence, emits the event for screens, publishes the activity, logs result.
|
|
126
127
|
* If errors is empty -> success, otherwise -> failure + dead letter + throws.
|
|
127
128
|
* @throws Error if there are any errors
|
|
128
129
|
*/
|
|
@@ -141,14 +142,7 @@ export class EventBus {
|
|
|
141
142
|
loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - FAILED: ${errorMessage}`);
|
|
142
143
|
}
|
|
143
144
|
UIEventBus.emit(event.name, event);
|
|
144
|
-
|
|
145
|
-
event: event.name,
|
|
146
|
-
label: event.label,
|
|
147
|
-
success,
|
|
148
|
-
attempts: event.attempts,
|
|
149
|
-
attemptLimit: EventBus.MAX_ATTEMPTS,
|
|
150
|
-
error: errorMessage,
|
|
151
|
-
});
|
|
145
|
+
this.publishQueue(event, success ? "succeeded" : "failed", errorMessage);
|
|
152
146
|
if (!success) {
|
|
153
147
|
throw new Error(errorMessage);
|
|
154
148
|
}
|
|
@@ -162,12 +156,15 @@ export class EventBus {
|
|
|
162
156
|
}
|
|
163
157
|
catch (err) {
|
|
164
158
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
165
|
-
errors.push(errorMessage);
|
|
166
159
|
loggerQueueProcessor.warn(`EVENT=${event.name} - Subscriber failed: ${errorMessage}`);
|
|
167
|
-
if (err instanceof DomainNetworkError) {
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
if (err instanceof DomainNetworkError || err instanceof RepeatableFailure) {
|
|
161
|
+
if (err instanceof DomainNetworkError) {
|
|
162
|
+
this.internetConnected = false;
|
|
163
|
+
UIEventBus.emit(InternetIsDownEvent.name);
|
|
164
|
+
}
|
|
165
|
+
throw new RepeatableFailure(errorMessage);
|
|
170
166
|
}
|
|
167
|
+
errors.push(errorMessage);
|
|
171
168
|
}
|
|
172
169
|
}
|
|
173
170
|
return errors;
|
|
@@ -220,7 +217,12 @@ export class EventBus {
|
|
|
220
217
|
/**
|
|
221
218
|
* Publishes a DomainEvent asynchronously - enqueues for later processing.
|
|
222
219
|
*/
|
|
220
|
+
static schedule() {
|
|
221
|
+
this.triggerProcessing();
|
|
222
|
+
}
|
|
223
223
|
static async publish(event) {
|
|
224
|
+
if (!event.correlationId)
|
|
225
|
+
event.applyChain(event.uuid);
|
|
224
226
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published ASYNC`);
|
|
225
227
|
await DomainEventRepository.save(event);
|
|
226
228
|
this.triggerProcessing();
|
|
@@ -231,6 +233,8 @@ export class EventBus {
|
|
|
231
233
|
* @throws Error if any subscriber fails or no subscribers registered
|
|
232
234
|
*/
|
|
233
235
|
static async publishSync(event) {
|
|
236
|
+
if (!event.correlationId)
|
|
237
|
+
event.applyChain(event.uuid);
|
|
234
238
|
loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published SYNC`);
|
|
235
239
|
event.markAsProcessing();
|
|
236
240
|
await DomainEventRepository.save(event);
|
|
@@ -239,8 +243,18 @@ export class EventBus {
|
|
|
239
243
|
return;
|
|
240
244
|
}
|
|
241
245
|
const subscriberList = this.subscribers.get(event.name);
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
try {
|
|
247
|
+
const errors = await this.executeSubscribers(event, subscriberList);
|
|
248
|
+
await this.postProcess(event, errors);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
if (err instanceof RepeatableFailure) {
|
|
252
|
+
event.retry();
|
|
253
|
+
await DomainEventRepository.save(event);
|
|
254
|
+
this.publishQueue(event, "idle");
|
|
255
|
+
}
|
|
256
|
+
throw err;
|
|
257
|
+
}
|
|
244
258
|
}
|
|
245
259
|
/**
|
|
246
260
|
* Processes all pending DomainEvents from the domain_events table.
|
|
@@ -250,18 +264,29 @@ export class EventBus {
|
|
|
250
264
|
static async drainAll() {
|
|
251
265
|
let event;
|
|
252
266
|
while ((event = await DomainEventRepository.findNextPending(this.internetConnected))) {
|
|
267
|
+
const current = event;
|
|
253
268
|
try {
|
|
254
|
-
|
|
255
|
-
await DomainEventRepository.save(
|
|
256
|
-
if (!this.preProcess(
|
|
257
|
-
await this.postProcess(
|
|
269
|
+
current.markAsProcessing();
|
|
270
|
+
await DomainEventRepository.save(current);
|
|
271
|
+
if (!this.preProcess(current)) {
|
|
272
|
+
await this.postProcess(current, ["No subscribers registered"]);
|
|
258
273
|
continue;
|
|
259
274
|
}
|
|
260
|
-
const subscriberList = this.subscribers.get(
|
|
261
|
-
const errors = await
|
|
262
|
-
|
|
275
|
+
const subscriberList = this.subscribers.get(current.name);
|
|
276
|
+
const errors = await runWithChain({
|
|
277
|
+
causationId: current.uuid,
|
|
278
|
+
correlationId: current.correlationId ?? current.uuid,
|
|
279
|
+
}, () => this.executeSubscribers(current, subscriberList));
|
|
280
|
+
await this.postProcess(current, errors);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
if (err instanceof RepeatableFailure) {
|
|
284
|
+
current.retry();
|
|
285
|
+
await DomainEventRepository.save(current);
|
|
286
|
+
this.publishQueue(current, "idle");
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
263
289
|
}
|
|
264
|
-
catch { }
|
|
265
290
|
}
|
|
266
291
|
}
|
|
267
292
|
/**
|
|
@@ -276,4 +301,14 @@ export class EventBus {
|
|
|
276
301
|
loggerQueueProcessor.warn("Failed to clear ProcessWorker queue:", error);
|
|
277
302
|
}
|
|
278
303
|
}
|
|
304
|
+
static publishQueue(event, status, detail) {
|
|
305
|
+
publishActivity({
|
|
306
|
+
channel: "queue",
|
|
307
|
+
name: event.name,
|
|
308
|
+
label: event.labelText(),
|
|
309
|
+
detail,
|
|
310
|
+
status,
|
|
311
|
+
ui: declaresUi(event),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
279
314
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BluetoothAdapter } from "../adapters/Bluetooth.adapter";
|
|
2
2
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
3
|
-
import {
|
|
4
|
-
import { UIEventBus } from "../infrastructure/ui/UIEventBus";
|
|
3
|
+
import { notifyDevice } from "../infrastructure/ui/activity";
|
|
5
4
|
class BluetoothService {
|
|
6
5
|
permissionStatus = null;
|
|
7
6
|
async requestPermissions() {
|
|
@@ -36,10 +35,11 @@ class BluetoothService {
|
|
|
36
35
|
loggerUseCases.info("Ensuring Bluetooth permissions for printer connection");
|
|
37
36
|
const permissions = await this.ensurePermissions();
|
|
38
37
|
if (!permissions) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
notifyDevice({
|
|
39
|
+
name: "bluetooth.required",
|
|
40
|
+
title: "Permisos de Bluetooth requeridos",
|
|
41
|
+
message: "Habilita los permisos de Bluetooth en configuración",
|
|
42
|
+
variant: "danger",
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
return permissions;
|
|
@@ -52,18 +52,20 @@ class BluetoothService {
|
|
|
52
52
|
}
|
|
53
53
|
showPermissionToast(permissions) {
|
|
54
54
|
if (permissions.isGranted) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
notifyDevice({
|
|
56
|
+
name: "bluetooth.enabled",
|
|
57
|
+
title: "Bluetooth habilitado",
|
|
58
|
+
message: "Permisos de Bluetooth concedidos",
|
|
59
|
+
variant: "success",
|
|
59
60
|
});
|
|
60
61
|
loggerUseCases.info("Bluetooth permissions granted");
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
notifyDevice({
|
|
65
|
+
name: "bluetooth.denied",
|
|
66
|
+
title: "Bluetooth no disponible",
|
|
67
|
+
message: "Los permisos de Bluetooth fueron denegados",
|
|
68
|
+
variant: "danger",
|
|
67
69
|
});
|
|
68
70
|
loggerUseCases.warn("Bluetooth permissions denied", { permissions });
|
|
69
71
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IntegrationEvent } from "../domain/events";
|
|
2
2
|
declare class DeadLetterQueueUseCases {
|
|
3
3
|
private get repository();
|
|
4
4
|
/**
|
|
5
5
|
* Retrieves all failed events from the dead letter queue.
|
|
6
6
|
*/
|
|
7
|
-
getFailedEvents(): Promise<
|
|
7
|
+
getFailedEvents(): Promise<IntegrationEvent[]>;
|
|
8
8
|
/**
|
|
9
9
|
* Retrieves a specific failed event by uuid.
|
|
10
10
|
*/
|
|
11
|
-
getFailedEventById(uuid: string): Promise<
|
|
11
|
+
getFailedEventById(uuid: string): Promise<IntegrationEvent | null>;
|
|
12
12
|
/**
|
|
13
13
|
* Manually retries a failed event by re-queuing it for processing.
|
|
14
14
|
* This removes the event from the dead letter queue and adds it back to the processing queue.
|
|
15
15
|
*/
|
|
16
|
-
retryFailedEvent(event:
|
|
16
|
+
retryFailedEvent(event: IntegrationEvent): Promise<void>;
|
|
17
17
|
/**
|
|
18
18
|
* Retries multiple failed events in batch.
|
|
19
19
|
*/
|
|
20
|
-
retryMultipleFailedEvents(events:
|
|
20
|
+
retryMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
|
|
21
21
|
success: number;
|
|
22
22
|
failed: number;
|
|
23
23
|
}>;
|
|
@@ -25,11 +25,11 @@ declare class DeadLetterQueueUseCases {
|
|
|
25
25
|
* Permanently deletes a failed event from the dead letter queue.
|
|
26
26
|
* Use with caution as this action cannot be undone.
|
|
27
27
|
*/
|
|
28
|
-
deleteFailedEvent(event:
|
|
28
|
+
deleteFailedEvent(event: IntegrationEvent): Promise<void>;
|
|
29
29
|
/**
|
|
30
30
|
* Deletes multiple failed events in batch.
|
|
31
31
|
*/
|
|
32
|
-
deleteMultipleFailedEvents(events:
|
|
32
|
+
deleteMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
|
|
33
33
|
success: number;
|
|
34
34
|
failed: number;
|
|
35
35
|
}>;
|
|
@@ -27,9 +27,7 @@ class DeadLetterQueueUseCases {
|
|
|
27
27
|
async retryFailedEvent(event) {
|
|
28
28
|
loggerUseCases.info(`Manually retrying failed event: ${event.name} (uuid: ${event.uuid})`);
|
|
29
29
|
try {
|
|
30
|
-
// Reset the event for retry
|
|
31
30
|
event.retry();
|
|
32
|
-
// Re-queue the event using V2 API
|
|
33
31
|
await EventBus.publish(event);
|
|
34
32
|
// Remove from dead letter queue only after successful re-queuing
|
|
35
33
|
await this.repository.remove(event.uuid);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type IntegrationEvent } from "../domain/events";
|
|
2
2
|
declare class EventService {
|
|
3
|
-
listAllEvents(): Promise<
|
|
4
|
-
republishSync(event:
|
|
3
|
+
listAllEvents(): Promise<IntegrationEvent[]>;
|
|
4
|
+
republishSync(event: IntegrationEvent): Promise<void>;
|
|
5
5
|
}
|
|
6
6
|
export declare const eventService: EventService;
|
|
7
7
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DomainEventRepository } from "../adapters/repositories/domain_event.repository";
|
|
2
|
-
import { EEventStatus } from "../domain/
|
|
2
|
+
import { EEventStatus } from "../domain/events";
|
|
3
3
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
4
4
|
import { EventBus } from "../infrastructure/workers/EventBus";
|
|
5
5
|
class EventService {
|
|
@@ -2,6 +2,6 @@ import { NetworkStatus } from "../domain/connectivity";
|
|
|
2
2
|
export declare class NetworkUseCases {
|
|
3
3
|
private networkStatus;
|
|
4
4
|
getNetworkStatus(): Promise<NetworkStatus>;
|
|
5
|
-
|
|
5
|
+
private notifyOnChange;
|
|
6
6
|
}
|
|
7
7
|
export declare const networkUseCases: NetworkUseCases;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NetworkAdapter } from "../adapters/Network.adapter";
|
|
2
2
|
import { InternetIsDownEvent, InternetIsUpEvent } from "../domain/events";
|
|
3
3
|
import { loggerUseCases } from "../infrastructure/logger";
|
|
4
|
-
import {
|
|
4
|
+
import { notifyDevice } from "../infrastructure/ui/activity";
|
|
5
5
|
import { UIEventBus } from "../infrastructure/ui/UIEventBus";
|
|
6
6
|
export class NetworkUseCases {
|
|
7
7
|
networkStatus = null;
|
|
@@ -13,29 +13,31 @@ export class NetworkUseCases {
|
|
|
13
13
|
else {
|
|
14
14
|
UIEventBus.emit(InternetIsDownEvent.name, false);
|
|
15
15
|
}
|
|
16
|
-
this.
|
|
16
|
+
this.notifyOnChange(networkStatus);
|
|
17
17
|
this.networkStatus = networkStatus;
|
|
18
18
|
return this.networkStatus;
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
20
|
+
notifyOnChange(networkStatus) {
|
|
21
|
+
const changed = networkStatus.isConnected !== this.networkStatus?.isConnected;
|
|
22
|
+
if (!changed) {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
25
|
if (!networkStatus.isConnected) {
|
|
26
|
-
loggerUseCases.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
loggerUseCases.warn(`Network is down: ${networkStatus.type}`);
|
|
27
|
+
notifyDevice({
|
|
28
|
+
name: "network.offline",
|
|
29
|
+
title: "Estas desconectado",
|
|
30
|
+
message: "Sin conexión a internet",
|
|
31
|
+
variant: "danger",
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
|
-
loggerUseCases.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
loggerUseCases.info(`Network is up: ${networkStatus.type}`);
|
|
36
|
+
notifyDevice({
|
|
37
|
+
name: "network.online",
|
|
38
|
+
title: "Conectado",
|
|
39
|
+
message: `Conexión a través de ${networkStatus.type}`,
|
|
40
|
+
variant: "success",
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
}
|
|
@@ -9,7 +9,7 @@ declare class PrinterService {
|
|
|
9
9
|
getPairedDevices(): BluetoothDevice[];
|
|
10
10
|
getPairedPrinters(): PairedPrinter[];
|
|
11
11
|
isConnected(): boolean;
|
|
12
|
-
connect(address: string, name: string): Promise<boolean>;
|
|
12
|
+
connect(address: string, name: string, notify?: boolean): Promise<boolean>;
|
|
13
13
|
disconnect(): Promise<void>;
|
|
14
14
|
getSelectedPrinter(): Promise<ISelectedPrinter | null>;
|
|
15
15
|
saveSelectedPrinter(printer: ISelectedPrinter): Promise<void>;
|