Both backends declare and default ActivityLockTimeout but never read it — GetActivityWorkItem sets the lock expiration from OrchestrationLockTimeout. So an activity can never have a longer lock than an orchestration turn, and (since locks aren't renewed — Issue 2) any activity running longer than OrchestrationLockTimeout loses its lock mid-run → duplicate dispatch + ErrWorkItemLockLost.
Proof it's dead config:
$ grep -rn ActivityLockTimeout backend/sqlite/sqlite.go
backend/sqlite/sqlite.go:30: ActivityLockTimeout time.Duration # declaration
backend/sqlite/sqlite.go:50: ActivityLockTimeout: 2 * time.Minute, # default
$ grep -rn ActivityLockTimeout backend/postgres/postgres.go
backend/postgres/postgres.go:31: ActivityLockTimeout time.Duration # declaration
backend/postgres/postgres.go:55: ActivityLockTimeout: 2 * time.Minute, # default
(No other references — never used.)
GetActivityWorkItem uses the wrong field — backend/sqlite/sqlite.go:847 and backend/postgres/postgres.go (the line inside func (be *postgresBackend) GetActivityWorkItem, :856 in pristine):
now := time.Now().UTC()
newLockExpiration := now.Add(be.options.OrchestrationLockTimeout) // ← should be ActivityLockTimeout
For contrast, GetOrchestrationWorkItem is correct in both (sqlite.go:754, postgres.go:766): now.Add(be.options.OrchestrationLockTimeout).
Repro: both timeouts = 10s; activity sleeps 30s → activity dispatched more than once, first completion logs lock on work-item was lost; raising ActivityLockTimeout has no effect.
Proposed diffs
--- a/backend/sqlite/sqlite.go
+++ b/backend/sqlite/sqlite.go
@@ func (be *sqliteBackend) GetActivityWorkItem(ctx context.Context) (*backend.ActivityWorkItem, error) {
now := time.Now().UTC()
- newLockExpiration := now.Add(be.options.OrchestrationLockTimeout)
- newLockExpiration := now.Add(be.options.ActivityLockTimeout)
--- a/backend/postgres/postgres.go
+++ b/backend/postgres/postgres.go
@@ func (be *postgresBackend) GetActivityWorkItem(ctx context.Context) (*backend.ActivityWorkItem, error) {
now := time.Now().UTC()
- newLockExpiration := now.Add(be.options.OrchestrationLockTimeout)
- newLockExpiration := now.Add(be.options.ActivityLockTimeout)
Both backends declare and default ActivityLockTimeout but never read it — GetActivityWorkItem sets the lock expiration from OrchestrationLockTimeout. So an activity can never have a longer lock than an orchestration turn, and (since locks aren't renewed — Issue 2) any activity running longer than OrchestrationLockTimeout loses its lock mid-run → duplicate dispatch + ErrWorkItemLockLost.
Proof it's dead config:
$ grep -rn ActivityLockTimeout backend/sqlite/sqlite.go
backend/sqlite/sqlite.go:30: ActivityLockTimeout time.Duration # declaration
backend/sqlite/sqlite.go:50: ActivityLockTimeout: 2 * time.Minute, # default
$ grep -rn ActivityLockTimeout backend/postgres/postgres.go
backend/postgres/postgres.go:31: ActivityLockTimeout time.Duration # declaration
backend/postgres/postgres.go:55: ActivityLockTimeout: 2 * time.Minute, # default
(No other references — never used.)
GetActivityWorkItem uses the wrong field — backend/sqlite/sqlite.go:847 and backend/postgres/postgres.go (the line inside func (be *postgresBackend) GetActivityWorkItem, :856 in pristine):
now := time.Now().UTC()
newLockExpiration := now.Add(be.options.OrchestrationLockTimeout) // ← should be ActivityLockTimeout
For contrast, GetOrchestrationWorkItem is correct in both (sqlite.go:754, postgres.go:766): now.Add(be.options.OrchestrationLockTimeout).
Repro: both timeouts = 10s; activity sleeps 30s → activity dispatched more than once, first completion logs lock on work-item was lost; raising ActivityLockTimeout has no effect.
Proposed diffs
--- a/backend/sqlite/sqlite.go
+++ b/backend/sqlite/sqlite.go
@@ func (be *sqliteBackend) GetActivityWorkItem(ctx context.Context) (*backend.ActivityWorkItem, error) {
now := time.Now().UTC()
--- a/backend/postgres/postgres.go
+++ b/backend/postgres/postgres.go
@@ func (be *postgresBackend) GetActivityWorkItem(ctx context.Context) (*backend.ActivityWorkItem, error) {
now := time.Now().UTC()