Skip to content

Commit 531e21a

Browse files
authored
Merge pull request #1591 from tkan145/refactor-synchronization
fix(synchronization): correctly cleanup key
2 parents 63ca457 + 4f573b9 commit 531e21a

4 files changed

Lines changed: 40 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1818
- Only validate oidc setting if authentication method is set to oidc [PR #1568](https://github.com/3scale/APIcast/pull/1568) [THREESCALE-11441](https://issues.redhat.com/browse/THREESCALE-11441)
1919
- Reduce memory consumption when returning large response that has been routed through a proxy server. [PR #1572](https://github.com/3scale/APIcast/pull/1572) [THREESCALE-12258](https://issues.redhat.com/browse/THREESCALE-12258)
2020
- Fix proxy policy doesn't send headers set by APIcast to the API Backend. [PR #1588](https://github.com/3scale/APIcast/pull/1588) [THREESCALE-10151](https://redhat.atlassian.net/browse/THREESCALE-10151)
21+
- Ensure the synchronization key is released correctly. [PR #1591](https://github.com/3scale/APIcast/pull/1590)
2122

2223
### Added
2324
- Update APIcast schema manifest [PR #1550](https://github.com/3scale/APIcast/pull/1550)

gateway/src/resty/resolver.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,11 @@ function _M.get_servers(self, qname, opts)
398398

399399
-- TODO: pass proper options to dns resolver (like SRV query type)
400400

401-
local sema, key = synchronization:acquire(format('qname:%s:qtype:%s', qname, 'A'))
401+
local key = format('qname:%s:qtype:%s', qname, 'A')
402+
local sema, err = synchronization:acquire(key)
403+
if not sema then
404+
return nil, "failed to acquire lock on key: " .. key .. 'error: ' .. err
405+
end
402406
local ok = sema:wait(0)
403407

404408
local answers, err = self:lookup(qname, not ok)

gateway/src/resty/synchronization.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function _M:acquire(key)
3939
if not semaphores then
4040
return nil, 'not initialized'
4141
end
42-
return semaphores[key], key
42+
return semaphores[key], nil
4343
end
4444

4545
--- release semaphore
@@ -60,7 +60,7 @@ end
6060
-- @param ...: the variable number of arguments that are going to be send to the callback function.
6161
function _M:run(key, timeout, callback, ...)
6262
local sema, err = self:acquire(key)
63-
if err ~= key then
63+
if not sema then
6464
ngx.log(ngx.WARN, 'failed to acquire lock on key: ', key, ' error: ', err)
6565
return false
6666
end
@@ -75,7 +75,7 @@ function _M:run(key, timeout, callback, ...)
7575
local ret, result, execute_error = task:execute(...)
7676

7777
if lock_acquired then
78-
self.release(key)
78+
self:release(key)
7979
sema:post()
8080
end
8181

spec/synchronization_spec.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,37 @@ describe("Synchronization", function()
6060
assert.same(err, "not initialized")
6161
end)
6262

63+
it("run releases the lock so a subsequent acquire succeeds", function()
64+
local callback = function() return 1 end
65+
66+
local ret, result = synchronization:run(key, 4, callback)
67+
assert.same(ret, true)
68+
assert.same(result, {1})
69+
70+
-- If run properly released the lock, a non-blocking acquire+wait should succeed
71+
local sema = synchronization:acquire(key)
72+
local ok = sema:wait(0)
73+
assert.is_true(ok, "expected lock to be available after run completed")
74+
75+
synchronization:release(key)
76+
sema:post()
77+
end)
78+
79+
it("run releases the lock even when callback throws", function()
80+
local callback = function() error("boom") end
81+
82+
local ret, _, execute_error = synchronization:run(key, 4, callback)
83+
assert.same(ret, false)
84+
assert.is_truthy(execute_error)
85+
86+
local sema = synchronization:acquire(key)
87+
local ok = sema:wait(0)
88+
assert.is_true(ok, "expected lock to be available after failed run")
89+
90+
synchronization:release(key)
91+
sema:post()
92+
end)
93+
6394
it("validate that acquire/release workflow", function()
6495

6596
local sema, _ = synchronization:acquire(key)

0 commit comments

Comments
 (0)