Skip to content

Commit b593668

Browse files
committedJul 31, 2024
fix(data structures): use maps instead of lists for data structures
1 parent d3a8ef6 commit b593668

File tree

3 files changed

+81
-49
lines changed

3 files changed

+81
-49
lines changed
 

‎src/common/main.lua

+22-14
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ main.init = function()
1414
-- Example ANT structure
1515
-- ANTS["antId"] = {
1616
-- Owner = "userId",
17-
-- Controllers = {"userId1", "userId2"},
17+
-- Controllers = {"userId1" = true, "userId2" = true},
1818
-- }
1919
ANTS = ANTS or {}
2020

2121
-- Example ADDRESSES structure - keyed references to the above ANTS structure
22-
-- ADDRESSES["userAddress"] = {["antProcessId1"] = ANTS["antProcessId1"], ANTS["antProcessId2"]}
22+
-- ADDRESSES["userAddress"] = {"antProcessId1" = true, "antProcessId2" = true}
2323
ADDRESSES = ADDRESSES or {}
2424

2525
--[[
@@ -71,11 +71,14 @@ main.init = function()
7171
assert(type(antId) == "string", "Process-Id tag is required")
7272
assert(ANTS[antId] == nil, "ANT is already registered")
7373

74-
ANTS[antId] = {
75-
Owner = nil,
76-
Controllers = {},
77-
}
78-
74+
utils.register({
75+
id = antId,
76+
timestamp = tonumber(msg.Timestamp),
77+
})
78+
--[[
79+
Send a request message for current ANT state to the process. Expect back
80+
a State-Notice so that we can update the registered ANT settings.
81+
]]
7982
ao.send({
8083
Target = antId,
8184
Action = "State",
@@ -93,12 +96,12 @@ main.init = function()
9396

9497
-- Register the ANT if not already registered
9598
if not isRegistered then
96-
ANTS[msg.From] = {
97-
Owner = stateRes.Owner,
98-
Controllers = {},
99-
-- for cleaning function
100-
RegisteredAt = tonumber(msg.Timestamp),
101-
}
99+
utils.register({
100+
id = msg.From,
101+
timestamp = tonumber(msg.Timestamp),
102+
owner = stateRes.Owner,
103+
controllers = stateRes.Controllers,
104+
})
102105
end
103106

104107
utils.updateAssociations(msg.From, stateRes)
@@ -117,7 +120,12 @@ main.init = function()
117120
local address = msg.Tags["Address"]
118121
assert(type(address) == "string", "Address is required")
119122

120-
local antIds = ADDRESSES[address] or {}
123+
local antIds = {}
124+
if ADDRESSES[address] then
125+
for antId, _ in pairs(ADDRESSES[address]) do
126+
table.insert(antIds, antId)
127+
end
128+
end
121129

122130
-- Send the list of ant_ids as a JSON array
123131
ao.send({

‎src/common/utils.lua

+57-33
Original file line numberDiff line numberDiff line change
@@ -242,54 +242,78 @@ function utils.indexOf(t, value)
242242
return -1
243243
end
244244

245-
function utils.updateUserAssociations(antId, state, user)
246-
-- remove previous associations
247-
if ADDRESSES[user] and user ~= state.Owner and not utils.includes(user, state.Controllers) then
248-
local antIndex = utils.indexOf(ADDRESSES[user], antId)
249-
if antIndex then
250-
table.remove(ADDRESSES[user], antIndex)
251-
end
252-
end
245+
--- func description
246+
-- @param {table} params
247+
-- @param {string} params.id
248+
-- @param {number} params.timestamp
249+
-- @param {string | nil} params.owner
250+
-- @param {table | nil} params.controllers
251+
function utils.register(params)
252+
assert(type(params) == "table", "Register Params must be a table")
253+
local id, timestamp, owner, controllers = params.id, params.timestamp, params.owner, params.controllers
254+
assert(type(id) == "string", "ANT ID must be a string")
255+
assert(type(timestamp) == "number", "Timestamp must be a number")
256+
assert(type(owner) == "string" or owner == nil, "Owner must be a string")
257+
assert(type(controllers) == "table" or controllers == nil, "Controllers must be a table")
258+
ANTS[id] = {
259+
Owner = owner,
260+
Controllers = controllers or {},
261+
RegisteredAt = timestamp,
262+
}
263+
end
253264

254-
-- add new associations
255-
if user == state.Owner or utils.includes(user, state.Controllers) then
256-
if not ADDRESSES[user] then
257-
ADDRESSES[user] = {}
258-
end
259-
if not utils.includes(antId, ADDRESSES[user]) then
260-
table.insert(ADDRESSES[user], antId)
261-
end
265+
function utils.controllerTableFromArray(t)
266+
assert(type(t) == "table", "argument needs to be a table")
267+
local map = {}
268+
for _, v in ipairs(t) do
269+
map[v] = true
262270
end
271+
return map
263272
end
264273

265274
function utils.updateAssociations(antId, state)
266275
-- Remove previous associations for old owner and controllers
267-
local previousOwner = ANTS[antId].Owner
268-
local previousControllers = ANTS[antId].Controllers
276+
local oldAnt = ANTS[antId]
277+
278+
local newOwner = state.Owner or "nilOwner"
279+
local newControllers = utils.controllerTableFromArray(state.Controllers)
269280

270-
if previousOwner and previousOwner ~= state.Owner and type(ANTS[antId]) == "table" then
271-
utils.updateUserAssociations(antId, ANTS[antId], previousOwner)
281+
local newAffliates = {}
282+
newAffliates[newOwner] = true
283+
for user, _ in pairs(newControllers) do
284+
newAffliates[user] = true
272285
end
273286

274-
for _, user in ipairs(previousControllers) do
275-
if not utils.includes(user, state.Controllers) then
276-
utils.updateUserAssociations(antId, ANTS[antId], user)
287+
if oldAnt ~= nil then
288+
local previousOwner = ANTS[antId].Owner or "nilOwner"
289+
local previousControllers = ANTS[antId].Controllers
290+
291+
local oldAffliates = {}
292+
oldAffliates[previousOwner] = true
293+
for user, _ in pairs(previousControllers) do
294+
oldAffliates[user] = true
277295
end
278-
end
279296

280-
-- Add new associations for new owner and controllers
281-
local users = { state.Owner }
282-
for _, user in ipairs(state.Controllers) do
283-
table.insert(users, user)
297+
for oldAffliate, _ in pairs(oldAffliates) do
298+
if not newAffliates[oldAffliate] and ADDRESSES[oldAffliate] then
299+
ADDRESSES[oldAffliate][antId] = nil
300+
end
301+
end
284302
end
285303

286-
for _, user in ipairs(users) do
287-
utils.updateUserAssociations(antId, state, user)
304+
for user, _ in pairs(newAffliates) do
305+
ADDRESSES[user] = ADDRESSES[user] or {}
306+
ADDRESSES[user][antId] = true
288307
end
289-
290308
-- Update the ANTS table
291-
ANTS[antId].Owner = state.Owner
292-
ANTS[antId].Controllers = state.Controllers
309+
if not newOwner and #newControllers == 0 then
310+
ANTS[antId] = nil
311+
else -- remove ant from registry if it has no owner or controllers
312+
ANTS[antId] = {
313+
Owner = newOwner,
314+
Controllers = newControllers,
315+
}
316+
end
293317
end
294318

295319
-- it is possible to register an ANT that does not respond to the state request, so we need to clean up the ANTS table

‎test/register.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ describe('ANT Registration Cases', async () => {
6868
);
6969

7070
// if we have messages in this case we have errors
71-
console.log('stateNoticeResult', stateNoticeResult);
71+
7272
assert.strictEqual(stateNoticeResult.Messages.length, 0);
7373

7474
const allAntsResult = await sendMessage(
@@ -197,6 +197,6 @@ describe('ANT Registration Cases', async () => {
197197
const failureNotice = stateNoticeResult.Messages[0].Tags.find(
198198
(tag) => tag.name === 'Action',
199199
);
200-
assert.strictEqual(failureNotice.value, 'State-Notice-Failure');
200+
assert.strictEqual(failureNotice.value, 'Invalid-State-Notice-Notice');
201201
});
202202
});

0 commit comments

Comments
 (0)
Please sign in to comment.