Repository navigation
fix(sync): let td-sync admin create-user run while the server writes - #215
Merged
Merged
Conversation
jubishop
force-pushed
the
worktree-create-user-lock
branch
from
October 15, 2026 21:14
f68f5ca to
5a1fce0
Compare
CreateUser counted users and then inserted in one deferred transaction, so a write from a running server in between made it fail at once with "database is locked". It now takes the write lock up front with BEGIN IMMEDIATE, as ApproveDeviceChallengeAsOperator does, and the docs no longer say to stop the server first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
marcus
force-pushed
the
worktree-create-user-lock
branch
from
October 15, 2026 22:26
5a1fce0 to
21a5a66
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
serverdb.CreateUsercounted users and then inserted the new one in a deferred transaction. If another process wrote toserver.dbbetween those two steps, it failed immediately withdatabase is locked, without waiting for the busy timeout. As a result,td-sync admin create-userfailed against a running server, and #213 had to tell operators to stop the server first.CreateUsernow takes the write lock up front withBEGIN IMMEDIATEon a pinned connection, asApproveDeviceChallengeAsOperatordoes in #213. The count and the insert remain atomic, so only the first user becomes admin, and the error strings are unchanged.The HTTP sign-up and add-member paths share
CreateUser. On the server they already ran one at a time on its single connection. The only change for them is that they now wait out another process's write instead of failing.#213's "stop the server first" wording is removed from the admin usage line, the
runAdminCreateUsercomment, and the ops guide.Testing
TestAdminCreateUser_WhileServerWritescreates eight users as child processes while the test process keeps writing. It then reruns one to check that the command is still idempotent, and checks that only the first user is admin. It failed 19 of 20 runs on the old code and passed 30 of 30 after the change.make test,go vet ./..., andgofmtpass, and golangci-lint v2.13.1 withGOOS=linuxreports 0 issues.go test -race -count=1passes forcmd/td-sync,internal/serverdb, andinternal/api.🤖 Generated with Claude Code