package service import ( "context" "errors" "github.com/Tencent/WeKnora/internal/common/redislock" ) // Long page synthesis needs a renewable, token-owned lease. Redis failure // stops reduction instead of allowing unlocked writes; releasing a stale // owner can never delete a successor's lock. func (s *wikiIngestService) withSlugLock(ctx context.Context, kbID, slug string, fn func(context.Context) error) (bool, error) { if s.redisClient == nil { return true, fn(ctx) } acquired := false err := redislock.WithRenewableLockWait(ctx, s.redisClient, wikiSlugLockPrefix+kbID+":"+slug, wikiSlugLockTTL, wikiSlugLockTTL/3, wikiSlugLockWait, func(lockCtx context.Context) error { acquired = true if err := redislock.EnsureOwnership(lockCtx); err != nil { return err } return fn(lockCtx) }) if !acquired && ctx.Err() == nil && errors.Is(err, context.DeadlineExceeded) { return false, nil } return acquired, err } func verifyWikiSlugOwnership(ctx context.Context) error { return redislock.EnsureOwnership(ctx) }