session: make session/new get-or-create
CreateEmpty now returns (session, created, error): if a session with the given name already exists it is returned untouched instead of erroring, and only a freshly created session receives the provided cwd/workflow/ variant. The o script no longer suppresses errors from session/new, so real failures surface while re-creating an existing session stays a no-op success.
This commit is contained in:
parent
72239fe3d5
commit
3f9f4753ef
|
|
@ -332,16 +332,21 @@ func buildTreeSpec(cfg *Config) virtfs.FsNodeDecl {
|
||||||
if cwd == "" {
|
if cwd == "" {
|
||||||
return nil, fmt.Errorf("cwd is required")
|
return nil, fmt.Errorf("cwd is required")
|
||||||
}
|
}
|
||||||
sess, err := session.CreateEmpty(name, remote, yolo)
|
sess, created, err := session.CreateEmpty(name, remote, yolo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sess.SetCwd(cwd)
|
// Get-or-create: only a freshly created session takes the
|
||||||
if workflow != "" {
|
// provided configuration. An existing session is returned
|
||||||
sess.SetWorkflow(workflow)
|
// untouched.
|
||||||
}
|
if created {
|
||||||
if variant != "" {
|
sess.SetCwd(cwd)
|
||||||
sess.SetVariant(variant)
|
if workflow != "" {
|
||||||
|
sess.SetWorkflow(workflow)
|
||||||
|
}
|
||||||
|
if variant != "" {
|
||||||
|
sess.SetVariant(variant)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return []byte(sess.Name() + "\n"), nil
|
return []byte(sess.Name() + "\n"), nil
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,11 @@ func BuildAgentIndex(sess *Session) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateEmpty creates an empty session (no agent) and registers it.
|
// CreateEmpty creates an empty session (no agent) and registers it.
|
||||||
func CreateEmpty(name, remote string, yolo ...bool) (*Session, error) {
|
// CreateEmpty returns the session named `name`, creating it if it does not yet
|
||||||
|
// exist (get-or-create). created reports whether a new session was made; when
|
||||||
|
// false the returned session already existed and its configuration is left
|
||||||
|
// untouched — creation never mutates an existing session.
|
||||||
|
func CreateEmpty(name, remote string, yolo ...bool) (sess *Session, created bool, err error) {
|
||||||
sessID := util.NewUUID()
|
sessID := util.NewUUID()
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = sessID
|
name = sessID
|
||||||
|
|
@ -293,16 +297,16 @@ func CreateEmpty(name, remote string, yolo ...bool) (*Session, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Early check (non-atomic, avoids expensive setup in the common case).
|
// Early path: return the existing session without building a tool server.
|
||||||
mu.RLock()
|
mu.RLock()
|
||||||
_, exists := sessions[name]
|
existing := sessions[name]
|
||||||
mu.RUnlock()
|
mu.RUnlock()
|
||||||
if exists {
|
if existing != nil {
|
||||||
return nil, fmt.Errorf("session already exists: %s", name)
|
return existing, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(serverCtx)
|
ctx, cancel := context.WithCancel(serverCtx)
|
||||||
sess := NewEmpty(sessID, ctx, cancel)
|
sess = NewEmpty(sessID, ctx, cancel)
|
||||||
sess.SetName(name)
|
sess.SetName(name)
|
||||||
sess.Remote = remote
|
sess.Remote = remote
|
||||||
sess.Yolo = len(yolo) > 0 && yolo[0]
|
sess.Yolo = len(yolo) > 0 && yolo[0]
|
||||||
|
|
@ -317,7 +321,7 @@ func CreateEmpty(name, remote string, yolo ...bool) (*Session, error) {
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cancel()
|
cancel()
|
||||||
return nil, fmt.Errorf("setup tool server: %w", err)
|
return nil, false, fmt.Errorf("setup tool server: %w", err)
|
||||||
}
|
}
|
||||||
sess.Proc = infra.Proc
|
sess.Proc = infra.Proc
|
||||||
sess.Keeper = infra.Keeper
|
sess.Keeper = infra.Keeper
|
||||||
|
|
@ -328,19 +332,20 @@ func CreateEmpty(name, remote string, yolo ...bool) (*Session, error) {
|
||||||
sess.StartBypassLoop(pkgBypassNotify)
|
sess.StartBypassLoop(pkgBypassNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atomic check-and-insert to prevent races.
|
// Atomic check-and-insert. If another caller won the race, discard our
|
||||||
|
// freshly-built session and return theirs — still get-or-create.
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
if _, exists := sessions[name]; exists {
|
if won := sessions[name]; won != nil {
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
cancel()
|
cancel()
|
||||||
return nil, fmt.Errorf("session already exists: %s", name)
|
return won, false, nil
|
||||||
}
|
}
|
||||||
sessions[name] = sess
|
sessions[name] = sess
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
pkgLog.Info("created empty session %s (id=%s)", name, sessID)
|
pkgLog.Info("created empty session %s (id=%s)", name, sessID)
|
||||||
PublishEvent("session."+sessID+".new", name)
|
PublishEvent("session."+sessID+".new", name)
|
||||||
return sess, nil
|
return sess, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextUname generates a unique agent name (12 hex chars).
|
// NextUname generates a unique agent name (12 hex chars).
|
||||||
|
|
|
||||||
|
|
@ -281,8 +281,9 @@ cmd_new() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
local agent_cwd="${1:-$PWD}"
|
local agent_cwd="${1:-$PWD}"
|
||||||
# Create session if it doesn't exist
|
# session/new is get-or-create: creating an existing session is a no-op
|
||||||
printf 'name=%s\ncwd=%s\n' "$CTX_SESSION" "$agent_cwd" | ollie-9p write "session/new" 2>/dev/null || true
|
# success, so real failures now surface instead of being suppressed.
|
||||||
|
printf 'name=%s\ncwd=%s\n' "$CTX_SESSION" "$agent_cwd" | ollie-9p write "session/new"
|
||||||
# Create the agent
|
# Create the agent
|
||||||
printf 'name=%s\ncwd=%s\n' "$CTX_AGENT" "$agent_cwd" | ollie-9p write "session/$CTX_SESSION/agent/new"
|
printf 'name=%s\ncwd=%s\n' "$CTX_AGENT" "$agent_cwd" | ollie-9p write "session/$CTX_SESSION/agent/new"
|
||||||
echo "created: $CTX_SESSION/$CTX_AGENT"
|
echo "created: $CTX_SESSION/$CTX_AGENT"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue