(ctx context.Context)
| 529 | } |
| 530 | |
| 531 | func (c *counterInt64) tryAcquireLock(ctx context.Context) func() { |
| 532 | lock, err := c.registry.connector.Lock(ctx, c.key, c.registry.lockTtl) |
| 533 | if err != nil { |
| 534 | // Log differently based on error type |
| 535 | if strings.Contains(err.Error(), "lock already taken") { |
| 536 | c.registry.logger.Debug().Err(err).Str("key", c.key).Msg("lock held by another instance, proceeding with local lock") |
| 537 | } else if errors.Is(err, context.DeadlineExceeded) { |
| 538 | c.registry.logger.Warn().Err(err).Str("key", c.key).Msg("lock acquisition timed out waiting for other instance") |
| 539 | } else { |
| 540 | c.registry.logger.Warn().Err(err).Str("key", c.key).Msg("failed to remotely lock counter will only use local lock") |
| 541 | } |
| 542 | } |
| 543 | if lock != nil && !lock.IsNil() { |
| 544 | c.registry.logger.Debug().Str("key", c.key).Msg("acquired remote lock for counter") |
| 545 | return func() { |
| 546 | unlockCtx, cancel := context.WithTimeout(c.registry.appCtx, c.registry.lockTtl) |
| 547 | defer cancel() |
| 548 | if err := lock.Unlock(unlockCtx); err != nil { |
| 549 | // "lock was already expired" is expected when operations take longer than anticipated |
| 550 | if strings.Contains(err.Error(), "lock was already expired") { |
| 551 | c.registry.logger.Debug().Err(err).Str("key", c.key).Int64("lock_ttl_ms", c.registry.lockTtl.Milliseconds()).Msg("lock expired during operations (expected behavior)") |
| 552 | } else { |
| 553 | c.registry.logger.Debug().Err(err).Str("key", c.key).Int64("lock_ttl_ms", c.registry.lockTtl.Milliseconds()).Msg("failed to unlock counter, so it will be expired after ttl") |
| 554 | } |
| 555 | } else { |
| 556 | c.registry.logger.Debug().Str("key", c.key).Msg("released remote lock for counter") |
| 557 | } |
| 558 | } |
| 559 | } |
| 560 | return nil |
| 561 | } |
| 562 | |
| 563 | func (c *counterInt64) localState() CounterInt64State { |
| 564 | return CounterInt64State{ |
no test coverage detected