Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/heavy-shirts-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@powersync/service-core': patch
---

Improved sync rules storage cached parsed sync rules, accommodating different parsing options where necessary.
16 changes: 12 additions & 4 deletions packages/service-core/src/storage/mongo/MongoSyncBucketStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import * as util from '../../util/util-index.js';
import {
BucketDataBatchOptions,
BucketStorageBatch,
ReplicationCheckpoint,
CompactOptions,
DEFAULT_DOCUMENT_BATCH_LIMIT,
DEFAULT_DOCUMENT_CHUNK_LIMIT_BYTES,
FlushedResult,
ParseSyncRulesOptions,
PersistedSyncRulesContent,
ReplicationCheckpoint,
ResolveTableOptions,
ResolveTableResult,
StartBatchOptions,
Expand Down Expand Up @@ -53,7 +53,7 @@ export class MongoSyncBucketStorage
}
});

private parsedSyncRulesCache: SqlSyncRules | undefined;
private parsedSyncRulesCache: {parsed: SqlSyncRules, options: ParseSyncRulesOptions} | undefined;
private writeCheckpointAPI: WriteCheckpointAPI;

constructor(
Expand Down Expand Up @@ -104,8 +104,16 @@ export class MongoSyncBucketStorage
}

getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules {
this.parsedSyncRulesCache ??= this.sync_rules.parsed(options).sync_rules;
return this.parsedSyncRulesCache;
const {parsed, options: cachedOptions} = this.parsedSyncRulesCache ?? {};
/**
* Check if the cached sync rules, if present, had the same options.
* Parse sync rules if the options are different or if there is no cached value.
*/
if (!parsed || options.defaultSchema != cachedOptions?.defaultSchema ) {
this.parsedSyncRulesCache = {parsed: this.sync_rules.parsed(options).sync_rules, options};
}

return this.parsedSyncRulesCache!.parsed;
}

async getCheckpoint(): Promise<ReplicationCheckpoint> {
Expand Down
38 changes: 37 additions & 1 deletion packages/service-core/test/src/data_storage.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BucketDataBatchOptions, SaveOperationTag } from '@/storage/BucketStorage.js';
import { getUuidReplicaIdentityBson } from '@/util/util-index.js';
import { RequestParameters } from '@powersync/service-sync-rules';
import { describe, expect, test } from 'vitest';
import { fromAsync, oneFromAsync } from './stream_utils.js';
Expand All @@ -13,7 +14,6 @@ import {
StorageFactory,
testRules
} from './util.js';
import { getUuidReplicaIdentityBson } from '@/util/util-index.js';

const TEST_TABLE = makeTestTable('test', ['id']);

Expand Down Expand Up @@ -1460,4 +1460,40 @@ bucket_definitions:
replication_size_bytes: 0
});
});

test('invalidate cached parsed sync rules', async () => {
const sync_rules_content = testRules(
`
bucket_definitions:
by_workspace:
parameters:
- SELECT id as workspace_id FROM workspace WHERE
workspace."userId" = token_parameters.user_id
data: []
`
);

const bucketStorageFactory = await factory();
const syncBucketStorage = bucketStorageFactory.getInstance(sync_rules_content);

const parsedSchema1 = syncBucketStorage.getParsedSyncRules({
defaultSchema: 'public'
});

const parsedSchema2 = syncBucketStorage.getParsedSyncRules({
defaultSchema: 'public'
});

// These should be cached, this will be the same instance
expect(parsedSchema2).equals(parsedSchema1);
expect(parsedSchema1.getSourceTables()[0].schema).equals('public');

const parsedSchema3 = syncBucketStorage.getParsedSyncRules({
defaultSchema: 'databasename'
});

// The cache should not be used
expect(parsedSchema3).not.equals(parsedSchema2);
expect(parsedSchema3.getSourceTables()[0].schema).equals('databasename');
});
}
2 changes: 1 addition & 1 deletion packages/service-core/test/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function testRules(content: string): PersistedSyncRulesContent {
parsed(options) {
return {
id: 1,
sync_rules: SqlSyncRules.fromYaml(content, PARSE_OPTIONS),
sync_rules: SqlSyncRules.fromYaml(content, options),
slot_name: 'test'
};
},
Expand Down
Loading