feat: show price (WIP edit)
- fix: adb tcp connection unstable retry - fix: recipe not show by undefined machine status Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
parent
60424ebe5a
commit
3b70cc9fe8
8 changed files with 269 additions and 48 deletions
|
|
@ -14,9 +14,83 @@ import { handleAdbPayload } from '../handlers/adbPayloadHandler';
|
|||
import { adbWriter } from '../stores/adbWriter';
|
||||
import { WritableStream } from '@yume-chan/stream-extra';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import type Dice_2 from '@lucide/svelte/icons/dice-2';
|
||||
|
||||
let syncConnection: any = null;
|
||||
|
||||
function isRecoverableError(error: any): boolean {
|
||||
if (!error) return false;
|
||||
const errorMessage = error.message ? String(error.message).toLowerCase() : '';
|
||||
const errorName = error.name ? String(error.name).toLowerCase() : '';
|
||||
|
||||
// Network-related errors that are typically recoverable
|
||||
const recoverablePatterns = [
|
||||
'connection refused',
|
||||
'connection reset',
|
||||
'connection timeout',
|
||||
'network is unreachable',
|
||||
'host is unreachable',
|
||||
'temporary failure',
|
||||
'operation timed out',
|
||||
'failed to connect',
|
||||
'connection lost',
|
||||
'broken pipe',
|
||||
'socket closed',
|
||||
'eof',
|
||||
'end of file',
|
||||
'disconnected'
|
||||
];
|
||||
|
||||
for (const pattern of recoverablePatterns) {
|
||||
if (errorMessage.includes(pattern) || errorName.includes(pattern)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(error.name && error.name.includes('Error')) ||
|
||||
error.name.includes('Exception') ||
|
||||
error.name === 'IOError' ||
|
||||
error.name === 'NetworkError'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async function connectWithRetry<T>(
|
||||
connectionFn: () => Promise<T>,
|
||||
description: string,
|
||||
maxRetries: number = 5,
|
||||
baseDelayMs: number = 1000
|
||||
): Promise<T> {
|
||||
let lastError: any;
|
||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||
try {
|
||||
const timeoutPromise = new Promise<never>((_, reject) => {
|
||||
setTimeout(() => reject(new Error(`Connection timeout for ${description}`)), 10000);
|
||||
});
|
||||
const result = await Promise.race([connectionFn(), timeoutPromise]);
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
lastError = e;
|
||||
if (attempt === maxRetries - 1) {
|
||||
break;
|
||||
}
|
||||
if (!isRecoverableError(e)) {
|
||||
break;
|
||||
}
|
||||
const delay = Math.min(baseDelayMs * Math.pow(2, attempt) + Math.random() * 1000, 10000);
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
`failed to ${description} after ${maxRetries} attempts. Last error: ${lastError.message}`
|
||||
);
|
||||
}
|
||||
|
||||
export async function connnectViaWebUSB() {
|
||||
const device = await AdbDaemonWebUsbDeviceManager.BROWSER?.requestDevice();
|
||||
console.log('usb ok', globalThis.navigator.usb);
|
||||
|
|
@ -216,50 +290,79 @@ export async function push(path: string, obj: string) {
|
|||
}
|
||||
|
||||
// NOTE: adb reverse is not work by unavailable features support
|
||||
async function connectToAndroidServer() {
|
||||
try {
|
||||
let inst = getAdbInstance();
|
||||
if (!inst) {
|
||||
console.warn('adb instance not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// await push('/sdcard/coffeevending/enable_adb_block_watch', '1');
|
||||
|
||||
const stream = await inst.transport.connect(env.PUBLIC_BREW_CONN_PORT);
|
||||
const writer = stream.writable.getWriter();
|
||||
const reader = stream.readable.getReader();
|
||||
|
||||
console.log('checking on writer ', writer);
|
||||
adbWriter.set(writer);
|
||||
if (writer) {
|
||||
addNotification('INFO:Enable Brewing Mode T on machine');
|
||||
} else {
|
||||
addNotification('WARN:Brewing Mode T unavailable');
|
||||
|
||||
setTimeout(async () => {
|
||||
console.log('reconnecting android server');
|
||||
await connectToAndroidServer();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
handleAdbPayload(new TextDecoder().decode(value));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('read error', e);
|
||||
} finally {
|
||||
adbWriter.set(null);
|
||||
addNotification('WARN:Brewing Mode T Offline ...');
|
||||
async function connectToAndroidServer(maxRetries = 5) {
|
||||
let lastError: any;
|
||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||
try {
|
||||
let inst = getAdbInstance();
|
||||
if (!inst) {
|
||||
console.warn('adb instance not found');
|
||||
return;
|
||||
}
|
||||
})();
|
||||
} catch (err) {
|
||||
console.error('Connection failed. Suspect java running or not', err);
|
||||
addNotification('ERR:Fail to enable brewing mode T');
|
||||
|
||||
// add retry mechanism
|
||||
const stream = await connectWithRetry(
|
||||
async () => inst.transport.connect(env.PUBLIC_BREW_CONN_PORT),
|
||||
`connect to Android server port ${env.PUBLIC_BREW_CONN_PORT}`,
|
||||
3,
|
||||
500
|
||||
);
|
||||
|
||||
const writer = stream.writable.getWriter();
|
||||
const reader = stream.readable.getReader();
|
||||
|
||||
console.log('checking on writer ', writer);
|
||||
adbWriter.set(writer);
|
||||
if (writer) {
|
||||
addNotification('INFO:Enable Brewing Mode T on machine');
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
handleAdbPayload(new TextDecoder().decode(value));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('read error', e);
|
||||
if (isRecoverableError(e)) {
|
||||
throw e;
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
adbWriter.set(null);
|
||||
addNotification('WARN:Brewing Mode T Offline ...');
|
||||
}
|
||||
} else {
|
||||
addNotification('WARN:Brewing Mode T unavailable');
|
||||
|
||||
if (attempt < maxRetries - 1) {
|
||||
const delay = Math.min(500 * Math.pow(2, attempt) + Math.random() * 500, 5000);
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
continue;
|
||||
} else {
|
||||
throw new Error('Brewing Mode T unavailable after all retries');
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
lastError = err;
|
||||
|
||||
if (attempt == maxRetries - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isRecoverableError(err)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const delay = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 10000);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
|
||||
if (lastError) {
|
||||
console.error('Connection failed. Suspect java running or not', lastError);
|
||||
addNotification(`ERR:Fail to enable brewing mode T\n${lastError.message ?? ''}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue