Idempotent tunnel create: reuse existing, block UI double-submit
CI / test (push) Successful in 10m5s

Return the active tunnel for the same host:port:protocol instead of
starting a second Holesail instance; coalesce concurrent creates.
UI disables the create button and shows “already exists” feedback.
This commit is contained in:
2026-07-10 23:28:07 -04:00
parent f732cab26c
commit 74cd2f4a2e
5 changed files with 197 additions and 28 deletions
+28 -4
View File
@@ -621,18 +621,29 @@ export async function loadTunnelsView(opts = {}) {
}
}
/** Prevent double-submit while a create is in flight */
let tunnelCreateBusy = false
export async function createTunnelFromForm() {
const name = document.getElementById('tunnel-name')?.value?.trim()
const host = document.getElementById('tunnel-host')?.value?.trim() || '127.0.0.1'
const port = Number(document.getElementById('tunnel-port')?.value)
const protocol = document.getElementById('tunnel-protocol')?.value || 'tcp'
const secure = document.getElementById('tunnel-secure')?.checked !== false
const btn = document.getElementById('tunnel-create-btn')
if (!port || port < 1 || port > 65535) {
showAlert('warning', 'Enter a valid port (165535)')
return
}
if (tunnelCreateBusy) {
showAlert('info', 'Tunnel create already in progress…')
return
}
tunnelCreateBusy = true
if (btn) btn.disabled = true
try {
let createdUrl = ''
let wasExisting = false
const job = await runJob(`Tunnel ${host}:${port}`, [
{
id: 'create',
@@ -647,6 +658,8 @@ export async function createTunnelFromForm() {
secure,
})
const url = res?.tunnel?.url
wasExisting = Boolean(res?.existing)
if (wasExisting) log('Tunnel already active — reusing existing hs:// URL')
if (url) {
createdUrl = url
log(`URL: ${url}`)
@@ -656,20 +669,31 @@ export async function createTunnelFromForm() {
},
])
showJob(job)
markFeedbackShown('success', `Tunnel created for ${host}:${port}`)
const label = wasExisting
? `Tunnel already exists for ${host}:${port}`
: `Tunnel created for ${host}:${port}`
markFeedbackShown(wasExisting ? 'info' : 'success', label)
if (createdUrl && navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(createdUrl)
showAlert('success', 'Tunnel created — hs:// URL copied')
showAlert(
wasExisting ? 'info' : 'success',
wasExisting
? 'Tunnel already exists — hs:// URL copied'
: 'Tunnel created — hs:// URL copied'
)
} catch {
showAlert('success', 'Tunnel created')
showAlert(wasExisting ? 'info' : 'success', label)
}
} else {
showAlert('success', 'Tunnel created')
showAlert(wasExisting ? 'info' : 'success', label)
}
await loadTunnelsView()
} catch (err) {
if (!err?.viaJob) presentError(err, 'createTunnel', { showAlert })
} finally {
tunnelCreateBusy = false
if (btn) btn.disabled = false
}
}