77 lines
3.2 KiB
JavaScript
77 lines
3.2 KiB
JavaScript
|
|
import { describe, test } from 'node:test';
|
||
|
|
import assert from 'node:assert/strict';
|
||
|
|
import { Arbiter } from '../../src/core/Arbiter.js';
|
||
|
|
|
||
|
|
describe('Cache invalidation paths', () => {
|
||
|
|
test('relation lookup cache clears on removal', () => {
|
||
|
|
const arbiter = new Arbiter();
|
||
|
|
arbiter.addNode('user', 'user');
|
||
|
|
arbiter.addNode('doc', 'document');
|
||
|
|
arbiter.addRelation('user', 'can_read', 'doc', 1.0);
|
||
|
|
|
||
|
|
const srcId = arbiter.nodeIdByKey.get('user');
|
||
|
|
const dstId = arbiter.nodeIdByKey.get('doc');
|
||
|
|
const cacheKey = arbiter.relationManager._makeDirectCacheKey(srcId, 'can_read', dstId);
|
||
|
|
|
||
|
|
const relation = arbiter.relationManager.getDirectRelation(srcId, 'can_read', dstId);
|
||
|
|
assert.ok(relation);
|
||
|
|
// RF-08: cache state moved entirely to RelationCaches.
|
||
|
|
assert.ok(arbiter.relationManager._caches.relationLookupCache.has(cacheKey));
|
||
|
|
|
||
|
|
arbiter.removeRelation('user', 'can_read', 'doc');
|
||
|
|
assert.ok(!arbiter.relationManager._caches.relationLookupCache.has(cacheKey));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('value cache clears on relation modification', () => {
|
||
|
|
const arbiter = new Arbiter();
|
||
|
|
arbiter.addNode('user', 'user');
|
||
|
|
arbiter.addNode('account', 'account');
|
||
|
|
arbiter.addRelation('user', 'has_balance', 'account', 1.0, { value: 10 });
|
||
|
|
|
||
|
|
const srcId = arbiter.nodeIdByKey.get('user');
|
||
|
|
const dstId = arbiter.nodeIdByKey.get('account');
|
||
|
|
const cacheKey = arbiter.relationManager._makeValueCacheKey(srcId, 'has_balance', dstId);
|
||
|
|
|
||
|
|
const valueRelation = arbiter.relationManager.getValueRelation(srcId, 'has_balance', dstId);
|
||
|
|
assert.ok(valueRelation);
|
||
|
|
assert.ok(arbiter.relationManager._caches.valueLookupCache.has(cacheKey));
|
||
|
|
|
||
|
|
arbiter.relationManager._modifyRelation('user', 'has_balance', 'account', { value: 20 });
|
||
|
|
assert.ok(!arbiter.relationManager._caches.valueLookupCache.has(cacheKey));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('direct check cache clears on relation removal', () => {
|
||
|
|
const arbiter = new Arbiter();
|
||
|
|
arbiter.addNode('user', 'user');
|
||
|
|
arbiter.addNode('doc', 'document');
|
||
|
|
arbiter.addRelation('user', 'can_read', 'doc', 1.0);
|
||
|
|
arbiter.setRelationConfig('can_read', { type: 'direct' });
|
||
|
|
|
||
|
|
const result = arbiter.check('user', 'can_read', 'doc');
|
||
|
|
assert.strictEqual(result.possibility, 1.0);
|
||
|
|
|
||
|
|
const srcId = arbiter.keyManager.getStringId('user');
|
||
|
|
const dstId = arbiter.keyManager.getStringId('doc');
|
||
|
|
const cacheKey = arbiter.keyManager.createCompositeKey(srcId, 'can_read', dstId);
|
||
|
|
assert.ok(arbiter.directCheckCache.has(cacheKey));
|
||
|
|
|
||
|
|
arbiter.removeRelation('user', 'can_read', 'doc');
|
||
|
|
assert.ok(!arbiter.directCheckCache.has(cacheKey));
|
||
|
|
});
|
||
|
|
|
||
|
|
test('value cache invalidation schedules stale recompute', () => {
|
||
|
|
const arbiter = new Arbiter();
|
||
|
|
arbiter.addNode('user', 'user');
|
||
|
|
arbiter.addNode('account', 'account');
|
||
|
|
arbiter.addRelation('user', 'has_balance', 'account', 1.0, { value: 10 });
|
||
|
|
|
||
|
|
const srcId = arbiter.nodeIdByKey.get('user');
|
||
|
|
const dstId = arbiter.nodeIdByKey.get('account');
|
||
|
|
const valueRelation = arbiter.relationManager.getValueRelation(srcId, 'has_balance', dstId);
|
||
|
|
assert.ok(valueRelation);
|
||
|
|
|
||
|
|
arbiter.relationManager._modifyRelation('user', 'has_balance', 'account', { value: 20 });
|
||
|
|
assert.strictEqual(arbiter.valueManager.staleValueItemsIndex.size, 0);
|
||
|
|
});
|
||
|
|
});
|