Add link session preparation flow
- wire front link resolve/prepare routes - add orchestrator session command handling - update admin dashboards and device/link logic
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { errAsync, ResultAsync } from "neverthrow";
|
||||
import { db } from "@pkg/db";
|
||||
import { type Err } from "@pkg/result";
|
||||
import { ERROR_CODES, type Err } from "@pkg/result";
|
||||
import { FlowExecCtx } from "@core/flow.execution.context";
|
||||
import { CreateDevice, Device, DeviceStatus, UpdateDevice } from "./data";
|
||||
import { DeviceRepository } from "./repository";
|
||||
@@ -46,14 +46,20 @@ export class DeviceController {
|
||||
* Only succeeds if the device is currently online.
|
||||
*/
|
||||
allocate(fctx: FlowExecCtx, id: number): ResultAsync<Device, Err> {
|
||||
return this.repo.getById(fctx, id).andThen((dev) => {
|
||||
if (dev.status !== DeviceStatus.ONLINE || dev.inUse) {
|
||||
return errAsync(deviceErrors.deviceNotAvailable(fctx, id));
|
||||
return this.repo.allocateIfAvailable(fctx, id).orElse((error) => {
|
||||
if (error.code === ERROR_CODES.NOT_ALLOWED) {
|
||||
return this.repo
|
||||
.getById(fctx, id)
|
||||
.andThen((dev) => {
|
||||
if (dev.status !== DeviceStatus.ONLINE || dev.inUse) {
|
||||
return errAsync(deviceErrors.deviceNotAvailable(fctx, id));
|
||||
}
|
||||
return errAsync(error);
|
||||
})
|
||||
.orElse(() => errAsync(error));
|
||||
}
|
||||
return this.repo.update(fctx, id, {
|
||||
status: DeviceStatus.BUSY,
|
||||
inUse: true,
|
||||
});
|
||||
|
||||
return errAsync(error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ResultAsync, errAsync, okAsync } from "neverthrow";
|
||||
import { FlowExecCtx } from "@core/flow.execution.context";
|
||||
import { Database, asc, eq } from "@pkg/db";
|
||||
import { Database, and, asc, eq } from "@pkg/db";
|
||||
import { device } from "@pkg/db/schema";
|
||||
import { type Err } from "@pkg/result";
|
||||
import { logger } from "@pkg/logger";
|
||||
@@ -135,4 +135,40 @@ export class DeviceRepository {
|
||||
): ResultAsync<Device, Err> {
|
||||
return this.update(fctx, id, { status });
|
||||
}
|
||||
|
||||
allocateIfAvailable(fctx: FlowExecCtx, id: number): ResultAsync<Device, Err> {
|
||||
return traceResultAsync({
|
||||
name: "device.allocateIfAvailable",
|
||||
fctx,
|
||||
fn: () =>
|
||||
ResultAsync.fromPromise(
|
||||
this.db
|
||||
.update(device)
|
||||
.set({
|
||||
status: DeviceStatus.BUSY,
|
||||
inUse: true,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(device.id, id),
|
||||
eq(device.status, DeviceStatus.ONLINE),
|
||||
eq(device.inUse, false),
|
||||
),
|
||||
)
|
||||
.returning()
|
||||
.execute(),
|
||||
(e) =>
|
||||
deviceErrors.updateFailed(
|
||||
fctx,
|
||||
e instanceof Error ? e.message : String(e),
|
||||
),
|
||||
).andThen((rows) => {
|
||||
if (!rows[0]) {
|
||||
return errAsync(deviceErrors.deviceNotAvailable(fctx, id));
|
||||
}
|
||||
return okAsync(rows[0] as Device);
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user