Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(PE-7090): return records as sorted entries #35

Merged
merged 9 commits into from
Nov 13, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

- Refactored handlers to use a util that codifies responses on calls.
- Added documentation with luadoc types for improved linting.
- Records are now returned as an alphabetically sorted array of [undername, {transactionId, ttlSeconds}] with the '@' record being the first.

### Fixed

Expand Down
16 changes: 15 additions & 1 deletion src/common/records.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,21 @@ end
--- Get all records from the ANT
---@return string The encoded JSON representation of all records.
function records.getRecords()
return json.encode(Records)
local antRecords = utils.deepCopy(Records)
assert(antRecords, "Failed to copy Records")
dtfiedler marked this conversation as resolved.
Show resolved Hide resolved
local recordEntries = utils.entries(antRecords)
-- sort the records alphabetically, ensuring "@" record is first
table.sort(recordEntries, function(a, b)
if a[1] == "@" then
return true
end
if b[1] == "@" then
return false
end
return a[1] < b[1]
end)

return json.encode(recordEntries)
dtfiedler marked this conversation as resolved.
Show resolved Hide resolved
end

return records
10 changes: 10 additions & 0 deletions src/common/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ utils.values = function(t)
return values
end

---@param t table
---@return table<table>
utils.entries = function(t)
local entries = {}
for _, key in ipairs(utils.keys(t)) do
table.insert(entries, { key, t[key] })
end
return entries
end
dtfiedler marked this conversation as resolved.
Show resolved Hide resolved

function utils.hasMatchingTag(tag, value)
return Handlers.utils.hasMatchingTag(tag, value)
end
Expand Down
58 changes: 51 additions & 7 deletions test/records.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import assert from 'node:assert';
import {
AO_LOADER_HANDLER_ENV,
DEFAULT_HANDLE_OPTIONS,
STUB_ADDRESS,
} from '../tools/constants.mjs';

describe('aos Records', async () => {
Expand All @@ -21,14 +22,53 @@ describe('aos Records', async () => {
);
}

async function setRecord(
{ name, ttl = 3600, transactionId = STUB_ADDRESS },
mem,
) {
return handle(
{
Tags: [
{ name: 'Action', value: 'Set-Record' },
{ name: 'Sub-Domain', value: name },
{ name: 'TTL-Seconds', value: ttl },
{ name: 'Transaction-Id', value: transactionId },
],
},
mem,
);
}

async function getRecords(mem) {
const res = await handle(
{
Tags: [{ name: 'Action', value: 'Records' }],
},
mem,
);

return JSON.parse(res.Messages[0].Data);
}

it('should get the records of the ant', async () => {
const result = await handle({
Tags: [{ name: 'Action', value: 'Records' }],
});
const setRecordRes = await setRecord({ name: 'test-1' });
const setRecordRes2 = await setRecord(
{ name: 'test-2' },
setRecordRes.Memory,
);
const setRecordRes3 = await setRecord(
{ name: 'test-3' },
setRecordRes2.Memory,
);

const records = JSON.parse(result.Messages[0].Data);
const records = await getRecords(setRecordRes3.Memory);
assert(records);
assert(records['@']);
const recordsMap = Object.fromEntries(records);
assert(recordsMap['@']);
// assert record order
const undernames = Object.keys(recordsMap);
assert(undernames[0] == '@');
assert.strictEqual(undernames.at(-1), 'test-3');
});

it('should get a singular record of the ant', async () => {
Expand Down Expand Up @@ -62,7 +102,9 @@ describe('aos Records', async () => {
setRecordResult.Memory,
);

const record = JSON.parse(recordsResult.Messages[0].Data)['@'];
const record = Object.fromEntries(
JSON.parse(recordsResult.Messages[0].Data),
)['@'];
assert(record.transactionId === ''.padEnd(43, '3'));
assert(record.ttlSeconds === 3600);
});
Expand Down Expand Up @@ -115,7 +157,9 @@ describe('aos Records', async () => {
setRecordResult.Memory,
);

const record = JSON.parse(recordsResult.Messages[0].Data)['timmy'];
const record = Object.fromEntries(
JSON.parse(recordsResult.Messages[0].Data),
)['timmy'];
assert(record.transactionId === ''.padEnd(43, '3'));
assert(record.ttlSeconds === 3600);
});
Expand Down
Loading