mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-08 23:33:16 +08:00
Wait for workspaceRegistry before provisioning user workspaces.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e9040224fb
commit
f98d283118
3 changed files with 72 additions and 8 deletions
|
|
@ -699,13 +699,50 @@ function installSettingsSection(ctx, entry, hooks) {
|
|||
|
||||
|
||||
let _workspaceRegistry = null
|
||||
let _workspaceRegistryWaiters = []
|
||||
|
||||
function notifyWorkspaceRegistryReady(registry) {
|
||||
_workspaceRegistry = registry || null
|
||||
const waiters = _workspaceRegistryWaiters.splice(0)
|
||||
for (const w of waiters) {
|
||||
try { clearTimeout(w.timer) } catch { /* ignore */ }
|
||||
try { w.resolve(_workspaceRegistry) } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until workspaceRegistry inject fires (or timeout). */
|
||||
function whenWorkspaceRegistry(timeoutMs = 30000) {
|
||||
if (_workspaceRegistry) return Promise.resolve(_workspaceRegistry)
|
||||
return new Promise((resolve) => {
|
||||
const entry = {
|
||||
resolve,
|
||||
timer: setTimeout(() => {
|
||||
const i = _workspaceRegistryWaiters.indexOf(entry)
|
||||
if (i >= 0) _workspaceRegistryWaiters.splice(i, 1)
|
||||
resolve(_workspaceRegistry || null)
|
||||
}, timeoutMs),
|
||||
}
|
||||
_workspaceRegistryWaiters.push(entry)
|
||||
})
|
||||
}
|
||||
|
||||
async function ensureUserWorkspace(empNo) {
|
||||
if (!_userWorkspaces) return null
|
||||
try {
|
||||
let registry = _workspaceRegistry
|
||||
if (!registry) {
|
||||
registry = await whenWorkspaceRegistry(30000)
|
||||
}
|
||||
const root = _currentConfig?.workspaceRoot
|
||||
if (!registry) {
|
||||
console.warn(
|
||||
'[uds-auth] workspaceRegistry still unavailable after wait; mkdir only under',
|
||||
root || '(default $DSH_HOME/user-workspaces)',
|
||||
)
|
||||
}
|
||||
return await _userWorkspaces.ensureUserWorkspace(
|
||||
{ workspaceRegistryHandle: _workspaceRegistry },
|
||||
_currentConfig?.workspaceRoot,
|
||||
{ workspaceRegistryHandle: registry },
|
||||
root,
|
||||
empNo,
|
||||
)
|
||||
} catch (err) {
|
||||
|
|
@ -714,6 +751,21 @@ async function ensureUserWorkspace(empNo) {
|
|||
}
|
||||
}
|
||||
|
||||
async function rebindPendingUserWorkspaces() {
|
||||
if (!_userWorkspaces || !_workspaceRegistry) return
|
||||
try {
|
||||
const users = _userWorkspaces._map
|
||||
if (!users || typeof users.keys !== 'function') return
|
||||
for (const empNo of users.keys()) {
|
||||
const row = users.get(empNo)
|
||||
if (row && row.workspaceId) continue
|
||||
try { await ensureUserWorkspace(empNo) } catch { /* ignore */ }
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[uds-auth] rebindPendingUserWorkspaces failed:', err.message)
|
||||
}
|
||||
}
|
||||
|
||||
export async function apply(ctx, config = {}) {
|
||||
let source = () => mergeConfig(config)
|
||||
_currentConfig = source()
|
||||
|
|
@ -809,8 +861,9 @@ async function initServices(ctx, config) {
|
|||
})
|
||||
|
||||
ctx.inject(['workspaceRegistry'], (wctx) => {
|
||||
_workspaceRegistry = wctx.workspaceRegistry
|
||||
notifyWorkspaceRegistryReady(wctx.workspaceRegistry)
|
||||
ctx.logger?.info?.('[uds-auth] workspaceRegistry ready')
|
||||
void rebindPendingUserWorkspaces()
|
||||
})
|
||||
|
||||
installDshAcl(ctx, {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Per-user workspace provisioning under workspaceRoot/<empNo>.
|
||||
*/
|
||||
import { mkdir } from 'node:fs/promises'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { join, resolve, sep } from 'node:path'
|
||||
import { homedir } from 'node:os'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { dirname } from 'node:path'
|
||||
|
|
@ -100,16 +100,27 @@ export class UserWorkspaceStore {
|
|||
if (!registry && ctx && typeof ctx.get === 'function') {
|
||||
try { registry = ctx.get('workspaceRegistry') } catch { registry = undefined }
|
||||
}
|
||||
|
||||
const cached = this.get(empNo)
|
||||
if (registry && cached?.workspaceId && typeof registry.get === 'function') {
|
||||
try {
|
||||
const existing = registry.get(cached.workspaceId)
|
||||
if (existing) {
|
||||
return { path: cached.path || userPath, workspaceId: String(cached.workspaceId), workspace: existing }
|
||||
}
|
||||
} catch { /* fall through and recreate */ }
|
||||
}
|
||||
|
||||
if (!registry || typeof registry.create !== 'function') {
|
||||
console.warn('[uds-auth] workspaceRegistry unavailable; mkdir only:', userPath)
|
||||
this.set(empNo, { path: userPath, workspaceId: null })
|
||||
return { path: userPath, workspaceId: null, workspace: null }
|
||||
this.set(empNo, { path: userPath, workspaceId: cached?.workspaceId || null })
|
||||
return { path: userPath, workspaceId: cached?.workspaceId || null, workspace: null }
|
||||
}
|
||||
|
||||
const prev = getUserContext()
|
||||
const workspace = await withUserContext(
|
||||
{ ...(prev || {}), empNo, _internalProvision: true },
|
||||
() => registry.create(userPath),
|
||||
() => registry.create(userPath, String(empNo)),
|
||||
)
|
||||
const workspaceId = workspace?.id != null ? String(workspace.id) : null
|
||||
this.set(empNo, { path: userPath, workspaceId })
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uds-auth",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"description": "UDS authentication plugin for DeepSeek Harness with multi-tenant session isolation",
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue