fix: add timeout for device responses

This commit is contained in:
2024-03-05 18:12:56 +01:00
parent 7256dc50d4
commit 6ac2cd1993
3 changed files with 68 additions and 46 deletions

View File

@@ -40,6 +40,16 @@ export async function canAutoConnect() {
return getViablePorts().then(it => it.length === 1)
}
function timeout<T>(promise: Promise<T>, ms: number): Promise<T> {
let timer: number
return Promise.race([
promise,
new Promise<T>((_, reject) => {
timer = setTimeout(() => reject(new Error("Timeout")), ms) as unknown as number
}),
]).finally(() => clearTimeout(timer))
}
export class CharaDevice {
private port!: SerialPort
private reader!: ReadableStreamDefaultReader<string>
@@ -124,15 +134,25 @@ export class CharaDevice {
}
private async internalRead() {
const {value} = await this.reader.read()
serialLog.update(it => {
it.push({
type: "output",
value: value!,
try {
const {value} = await timeout(this.reader.read(), 5000)
serialLog.update(it => {
it.push({
type: "output",
value: value!,
})
return it
})
return it
})
return value!
return value!
} catch (e) {
serialLog.update(it => {
it.push({
type: "output",
value: `${e}`,
})
return it
})
}
}
/**
@@ -169,31 +189,32 @@ export class CharaDevice {
}
const send = this.internalSend.bind(this)
const read = this.internalRead.bind(this)
const exec = new Promise<T>(async resolve => {
let result!: T
try {
if (this.suspendDebounceId) {
clearTimeout(this.suspendDebounceId)
} else {
await this.wake()
}
result = await callback(send, read)
} finally {
delete this.lock
this.suspendDebounceId = setTimeout(() => {
// cannot be locked here as all the code until clearTimeout is sync
console.assert(this.lock === undefined)
this.lock = this.suspend().then(() => {
delete this.lock
delete this.suspendDebounceId
return true
})
}, this.suspendDebounce) as any
resolve(result)
}
let resolveLock: (result: true) => void
this.lock = new Promise<true>(resolve => {
resolveLock = resolve
})
this.lock = exec.then(() => true)
return exec
let result!: T
try {
if (this.suspendDebounceId) {
clearTimeout(this.suspendDebounceId)
} else {
await this.wake()
}
result = await callback(send, read)
} finally {
delete this.lock
this.suspendDebounceId = setTimeout(() => {
// cannot be locked here as all the code until clearTimeout is sync
console.assert(this.lock === undefined)
this.lock = this.suspend().then(() => {
delete this.lock
delete this.suspendDebounceId
return true
})
}, this.suspendDebounce) as any
resolveLock!(true)
return result
}
}
/**

View File

@@ -1,20 +1,25 @@
export class SemVer {
major: number
minor: number
patch: number
major = 0
minor = 0
patch = 0
preRelease?: string
meta?: string
constructor(versionString: string) {
const [, major, minor, patch, preRelease, meta] =
const result =
/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+))?$/.exec(
versionString,
)!
this.major = Number.parseInt(major)
this.minor = Number.parseInt(minor)
this.patch = Number.parseInt(patch)
if (preRelease) this.preRelease = preRelease
if (meta) this.meta = meta
)
if (!result) {
console.error("Invalid version string:", versionString)
} else {
const [, major, minor, patch, preRelease, meta] = result
this.major = Number.parseInt(major)
this.minor = Number.parseInt(minor)
this.patch = Number.parseInt(patch)
if (preRelease) this.preRelease = preRelease
if (meta) this.meta = meta
}
}
toString() {

View File

@@ -69,10 +69,6 @@
$: chordActions = chord?.actions.slice(chord.actions.lastIndexOf(0) + 1).toSorted(compare)
$: compoundIndices = chord?.actions.slice(0, chord.actions.indexOf(0))
$: {
console.log(chord?.actions, chordActions, compoundIndices)
}
</script>
<button