'How to avoid circular dependency in lua without global variables?
I'm using OpenResty and my app is setup as:
app/
clients/
photoClient.lua
init.lua
auth.lua
Let's say photoClient has both an unauthenticated and a authenticated endpoint (similar to an avatar endpoint that is accessible without logging in, but there may be private photos that you need to login first)
So in terms of dependencies, I have:
-- auth.lua
local photoClient = require('app.clients.photoClient')
-- this is used to show avatar on the login page
local auth = {}
auth.isAuthenticated = function ()
-- logic to check authentication
end
return auth
and the client is
-- photoClient.lua
local auth = require('app.auth')
local photoClient = {}
photoClient.privateEndpoint = function()
if (!auth.isAuthenticated()) {
ngx.exit(403)
}
...
end
photoClient.getAvator = function() {
-- this is a public method used by auth
}
return photoClient
This is giving me a circular dependency issue. I've seen on other SO post that you can use global variables, i.e. to do photoClient = photoClient or require('app.clients.photoClient') but I do not want to use global variables and want to keep each module scoped to itself.
How can I do this?
Solution 1:[1]
Found the solution on LuaFlare Documentation by Kate Adams: basically add package.loaded[...] = your_module before you do return your_module to every file, i.e.
-- auth.lua
local auth = {}
package.loaded[...] = auth
local photoClient = require('app.clients.photoClient')
...
return auth
-- photoClient.lua
local photoClient = {}
package.loaded[...] = photoClient
local auth = require('app.auth')
...
return photoClient
Fixed the problem. Here is the link to the book's page for anyone who is interested to read more.
Solution 2:[2]
Two main solutions:
Split
Split up auth into two modules that handle different aspects: an auth module for common logic that might be used by photoClient and a login module that is the login page.
This solution will prevent the same problem in other cases where you need to use auth.
Inject
In parent code (init.lua) that owns both of these modules, inject one into the other (call a function that passes the module).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Egor Skriptunoff |
| Solution 2 | idbrii |
