Enhance connection handling in DocumentPrinterClient
All checks were successful
farmcontrol/farmcontrol-server/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-server/pipeline/head This commit looks good
- Introduced connection state management with `isConnecting` to prevent multiple concurrent connection attempts. - Added `scheduleReconnect` method to handle reconnection logic with a delay. - Improved error handling and logging during connection and reconnection processes. - Updated `updateDocumentPrinterState` to optimize state updates and prevent unnecessary changes.
This commit is contained in:
parent
bb9b472559
commit
d5fe978361
@ -31,6 +31,8 @@ export class DocumentPrinterClient {
|
||||
this.state = { type: this.active == true ? "offline" : "inactive" };
|
||||
this.isOnline = documentPrinter.online || false;
|
||||
this.shouldReconnect = true;
|
||||
this.isConnecting = false;
|
||||
this.reconnectTimeout = null;
|
||||
this.isProcessingQueue = false;
|
||||
this.eventUpdateInterval = null;
|
||||
this.initializeInterface();
|
||||
@ -138,7 +140,37 @@ export class DocumentPrinterClient {
|
||||
});
|
||||
}
|
||||
|
||||
statesEqual(a, b) {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
a.type === b.type && a.message === b.message && a.progress === b.progress
|
||||
);
|
||||
}
|
||||
|
||||
scheduleReconnect(delay = 30000) {
|
||||
if (!this.shouldReconnect || this.active === false) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.reconnectTimeout = setTimeout(() => {
|
||||
this.reconnectTimeout = null;
|
||||
this.reconnect();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
async connect() {
|
||||
if (this.isConnecting) {
|
||||
logger.debug(
|
||||
`Already connecting to document printer ${this.documentPrinter.name}, skipping`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.active == false) {
|
||||
this.shouldReconnect = false;
|
||||
this.isOnline = false;
|
||||
@ -146,44 +178,58 @@ export class DocumentPrinterClient {
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
}
|
||||
logger.info(
|
||||
`Connecting to document printer ${this.id} (${this.interface})`,
|
||||
);
|
||||
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
// Always stop the event update interval when connecting
|
||||
clearInterval(this.eventUpdateInterval);
|
||||
this.eventUpdateInterval = null;
|
||||
this.state = { type: "connecting", message: null };
|
||||
this.isOnline = false;
|
||||
await this.updateDocumentPrinterState();
|
||||
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot connect: No interface initialized for ${this.interface}`,
|
||||
this.isConnecting = true;
|
||||
try {
|
||||
logger.info(
|
||||
`Connecting to document printer ${this.id} (${this.interface})`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await this.printerInterface.connect();
|
||||
|
||||
if (result.error) {
|
||||
logger.error(
|
||||
`Error connecting to document printer ${this.documentPrinter.name}:`,
|
||||
result.error,
|
||||
);
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.reconnectTimeout = null;
|
||||
// Always stop the event update interval when connecting
|
||||
clearInterval(this.eventUpdateInterval);
|
||||
this.eventUpdateInterval = null;
|
||||
this.state = { type: "connecting", message: null };
|
||||
this.isOnline = false;
|
||||
this.state = { type: "offline", message: result.error };
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
|
||||
if (!this.printerInterface) {
|
||||
logger.error(
|
||||
`Cannot connect: No interface initialized for ${this.interface}`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = await this.printerInterface.connect();
|
||||
|
||||
if (result.error) {
|
||||
logger.error(
|
||||
`Error connecting to document printer ${this.documentPrinter.name}:`,
|
||||
result.error,
|
||||
);
|
||||
this.isOnline = false;
|
||||
this.state = { type: "offline", message: result.error };
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
}
|
||||
logger.info(
|
||||
`Connected to document printer ${this.documentPrinter.name} (${this.interface})`,
|
||||
);
|
||||
return true;
|
||||
} finally {
|
||||
this.isConnecting = false;
|
||||
}
|
||||
logger.info(
|
||||
`Connected to document printer ${this.documentPrinter.name} (${this.interface})`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
async reconnect() {
|
||||
if (this.isConnecting) {
|
||||
logger.debug(
|
||||
`Document printer ${this.documentPrinter.name} is already connecting, skipping reconnect`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.active == false) {
|
||||
logger.info(
|
||||
`Document printer ${this.documentPrinter.name} is inactive, skipping reconnect`,
|
||||
@ -194,6 +240,10 @@ export class DocumentPrinterClient {
|
||||
await this.updateDocumentPrinterState();
|
||||
return false;
|
||||
}
|
||||
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.reconnectTimeout = null;
|
||||
|
||||
if (this.isOnline == true) {
|
||||
logger.info(
|
||||
`Disconnecting from document printer ${this.documentPrinter.name} before reconnecting...`,
|
||||
@ -207,25 +257,17 @@ export class DocumentPrinterClient {
|
||||
const connectResult = await this.connect();
|
||||
if (connectResult == false) {
|
||||
logger.error(
|
||||
`Error reconnecting to document printer ${this.documentPrinter.name}:`,
|
||||
connectResult.error,
|
||||
`Error reconnecting to document printer ${this.documentPrinter.name}`,
|
||||
);
|
||||
if (this.shouldReconnect) {
|
||||
// Attempt to reconnect after delay
|
||||
setTimeout(() => this.reconnect(), 30000);
|
||||
}
|
||||
this.scheduleReconnect();
|
||||
return false;
|
||||
}
|
||||
const initializeResult = await this.initialize();
|
||||
if (initializeResult == false) {
|
||||
logger.error(
|
||||
`Error initializing document printer ${this.documentPrinter.name}:`,
|
||||
initializeResult.error,
|
||||
`Error initializing document printer ${this.documentPrinter.name}`,
|
||||
);
|
||||
if (this.shouldReconnect) {
|
||||
// Attempt to reconnect after delay
|
||||
setTimeout(() => this.reconnect(), 30000);
|
||||
}
|
||||
this.scheduleReconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -281,17 +323,33 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
|
||||
async updateDocumentPrinterState() {
|
||||
const updateData = {
|
||||
online: this.isOnline,
|
||||
state: this.state,
|
||||
connectedAt: this.connectedAt ?? null,
|
||||
};
|
||||
|
||||
const currentConnectedAt = this.documentPrinter?.connectedAt;
|
||||
const connectedAtUnchanged =
|
||||
(currentConnectedAt?.toString?.() ?? null) ===
|
||||
(updateData.connectedAt?.toString?.() ?? null);
|
||||
|
||||
if (
|
||||
this.documentPrinter?.online === updateData.online &&
|
||||
this.statesEqual(this.documentPrinter?.state, updateData.state) &&
|
||||
connectedAtUnchanged
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.documentPrinter = { ...this.documentPrinter, ...updateData };
|
||||
|
||||
try {
|
||||
// Update state in database or via socket client
|
||||
// This can be implemented based on your database structure
|
||||
this.socketClient.editObject({
|
||||
await this.socketClient.editObject({
|
||||
_id: this.id,
|
||||
objectType: "documentPrinter",
|
||||
updateData: {
|
||||
online: this.isOnline,
|
||||
state: this.state,
|
||||
connectedAt: this.connectedAt,
|
||||
},
|
||||
updateData,
|
||||
auditLog: true,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(`Failed to update document printer state:`, error);
|
||||
@ -308,8 +366,7 @@ export class DocumentPrinterClient {
|
||||
|
||||
async updateJobState(jobId, state) {
|
||||
logger.info(`Updating job state for ${jobId}`);
|
||||
const notify =
|
||||
state?.type !== "deploying" && state?.type !== "queued";
|
||||
const notify = state?.type !== "deploying" && state?.type !== "queued";
|
||||
await this.socketClient.editObject({
|
||||
_id: jobId,
|
||||
objectType: "documentJob",
|
||||
@ -571,6 +628,8 @@ export class DocumentPrinterClient {
|
||||
async disconnect() {
|
||||
logger.info(`Disconnecting from ${this.documentPrinter.name}`);
|
||||
this.shouldReconnect = false;
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.reconnectTimeout = null;
|
||||
// Always stop the event update interval when disconnecting
|
||||
clearInterval(this.eventUpdateInterval);
|
||||
this.eventUpdateInterval = null;
|
||||
@ -583,7 +642,6 @@ export class DocumentPrinterClient {
|
||||
this.queue = []; // Clear queue on disconnect
|
||||
this.jobQuantities.clear();
|
||||
await this.updateDocumentPrinterState();
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
logger.info(`Successfully disconnected from ${this.documentPrinter.name}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -774,8 +774,6 @@ export class PrinterClient {
|
||||
);
|
||||
this.filamentDetected = newFilamentDetected;
|
||||
|
||||
console.log(this.currentFilamentStock);
|
||||
|
||||
if (newFilamentDetected == false && this.currentFilamentStock == null) {
|
||||
await this.database.removeAlertsByCode("noFilamentLoaded");
|
||||
await this.database.addAlert({
|
||||
@ -1175,9 +1173,12 @@ export class PrinterClient {
|
||||
|
||||
const remainingTime = this.deploySubJobTargetTime - now;
|
||||
clearTimeout(this.deploySubJobTimer);
|
||||
this.deploySubJobTimer = setTimeout(() => {
|
||||
this.processDeploySubJobQueue();
|
||||
}, Math.max(remainingTime, 0));
|
||||
this.deploySubJobTimer = setTimeout(
|
||||
() => {
|
||||
this.processDeploySubJobQueue();
|
||||
},
|
||||
Math.max(remainingTime, 0),
|
||||
);
|
||||
|
||||
await this.database.updateSubJobState(subJob._id, {
|
||||
type: "deploying",
|
||||
@ -1227,7 +1228,6 @@ export class PrinterClient {
|
||||
"with gcode file:",
|
||||
`${subJob.gcodeFile._id}`,
|
||||
);
|
||||
console.log("subJob", subJob);
|
||||
const gcodeFile = await this.socketClient.getObject({
|
||||
objectType: "gcodeFile",
|
||||
_id: subJob.gcodeFile._id,
|
||||
@ -1237,8 +1237,6 @@ export class PrinterClient {
|
||||
throw new Error("G-code file not found");
|
||||
}
|
||||
|
||||
console.log("gcodeFile", gcodeFile);
|
||||
|
||||
const fileId = (gcodeFile.file?._id || gcodeFile.file).toString();
|
||||
let deploymentActive = true;
|
||||
|
||||
@ -1517,9 +1515,7 @@ export class PrinterClient {
|
||||
|
||||
try {
|
||||
if (speedFactor === undefined || speedFactor === null) {
|
||||
logger.warn(
|
||||
`No speed factor provided for ${this.printer.name}`,
|
||||
);
|
||||
logger.warn(`No speed factor provided for ${this.printer.name}`);
|
||||
return this.printerActionResult(false, "No speed factor provided");
|
||||
}
|
||||
|
||||
@ -1550,7 +1546,10 @@ export class PrinterClient {
|
||||
}
|
||||
|
||||
async setExtrudeFactor({ extrudeFactor }) {
|
||||
logger.info(`Setting extrude factor for ${this.printer.name}:`, extrudeFactor);
|
||||
logger.info(
|
||||
`Setting extrude factor for ${this.printer.name}:`,
|
||||
extrudeFactor,
|
||||
);
|
||||
|
||||
if (!this.isOnline) {
|
||||
logger.error(
|
||||
@ -1564,9 +1563,7 @@ export class PrinterClient {
|
||||
|
||||
try {
|
||||
if (extrudeFactor === undefined || extrudeFactor === null) {
|
||||
logger.warn(
|
||||
`No extrude factor provided for ${this.printer.name}`,
|
||||
);
|
||||
logger.warn(`No extrude factor provided for ${this.printer.name}`);
|
||||
return this.printerActionResult(false, "No extrude factor provided");
|
||||
}
|
||||
|
||||
@ -1710,10 +1707,7 @@ export class PrinterClient {
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
squareCornerVelocity === undefined ||
|
||||
squareCornerVelocity === null
|
||||
) {
|
||||
if (squareCornerVelocity === undefined || squareCornerVelocity === null) {
|
||||
logger.warn(
|
||||
`No square corner velocity provided for ${this.printer.name}`,
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user