Skip to content

Commit

Permalink
Separate Hasura check to new function
Browse files Browse the repository at this point in the history
  • Loading branch information
darunrs committed Apr 17, 2024
1 parent 26ecb4c commit d0f7fb2
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
24 changes: 14 additions & 10 deletions runner/src/provisioner/provisioner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,15 @@ describe('Provisioner', () => {
await expect(provisioner.provisionUserApi(indexerConfig)).rejects.toThrow('Failed to provision endpoint: Failed to setup partitioned logs table: Failed to schedule log partition jobs: some error');
});

it('provisions and tracks logs and metadata table once, adds permissions twice', async () => {
it('provisions logs and metadata tables once', async () => {
hasuraClient.getTableNames = jest.fn().mockReturnValueOnce(['blocks']).mockReturnValue(['blocks', '__logs', '__metadata']);
await provisioner.provisionLogsAndMetadataIfNeeded(indexerConfig);
expect(hasuraClient.executeSqlOnSchema).toBeCalledTimes(2);
expect(cronPgClient.query).toBeCalledTimes(2);
expect(userPgClientQuery).toBeCalledTimes(2);
});

it('tracks logs and metadata table once, adds permissions twice', async () => {
hasuraClient.getTrackedTablePermissions = jest.fn().mockReturnValueOnce([]).mockReturnValueOnce([
{
table: {
Expand All @@ -279,27 +287,23 @@ describe('Provisioner', () => {
}
]);
hasuraClient.getTableNames = jest.fn().mockReturnValueOnce(['blocks']).mockReturnValueOnce(['blocks', '__logs', '__metadata']);
await provisioner.provisionLogsAndMetadataIfNeeded(indexerConfig);
await provisioner.provisionLogsAndMetadataIfNeeded(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);

expect(hasuraClient.executeSqlOnSchema).toBeCalledTimes(2);
expect(cronPgClient.query).toBeCalledTimes(2);
expect(hasuraClient.trackTables).toBeCalledTimes(1);
expect(hasuraClient.addPermissionsToTables).toBeCalledTimes(2);
});

it('provision logs and metadata table function caches result', async () => {
it('ensuring consistent state caches result', async () => {
hasuraClient.getTrackedTablePermissions = jest.fn().mockReturnValue([
generateTableConfig('morgs_near_test_function', 'blocks', 'morgs_near'),
generateTableConfig('morgs_near_test_function', '__logs', 'morgs_near'),
generateTableConfig('morgs_near_test_function', '__metadata', 'morgs_near'),
]);
hasuraClient.getTableNames = jest.fn().mockReturnValue(['blocks', '__logs', '__metadata']);
await provisioner.provisionLogsAndMetadataIfNeeded(indexerConfig);
await provisioner.provisionLogsAndMetadataIfNeeded(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);
await provisioner.ensureConsistentHasuraState(indexerConfig);

expect(hasuraClient.executeSqlOnSchema).not.toBeCalled();
expect(cronPgClient.query).not.toBeCalled();
expect(hasuraClient.trackTables).not.toBeCalled();
expect(hasuraClient.addPermissionsToTables).not.toBeCalled();
});
Expand Down
43 changes: 30 additions & 13 deletions runner/src/provisioner/provisioner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default class Provisioner {
tracer: Tracer = trace.getTracer('queryapi-runner-provisioner');
#hasBeenProvisioned: Record<string, Record<string, boolean>> = {};
#hasLogsMetadataBeenProvisioned: Record<string, Record<string, boolean>> = {};
#hasuraConsistentState: Record<string, Record<string, boolean>> = {};

constructor (
private readonly hasuraClient: HasuraClient = new HasuraClient(),
Expand Down Expand Up @@ -82,6 +83,11 @@ export default class Provisioner {
this.#hasBeenProvisioned[accountId][functionName] = true;
}

private setConsistentState (accountId: string, functionName: string): void {
this.#hasuraConsistentState[accountId] ??= {};
this.#hasuraConsistentState[accountId][functionName] = true;
}

async createDatabase (name: string): Promise<void> {
await this.adminDefaultPgClient.query(this.pgFormat('CREATE DATABASE %I', name));
}
Expand Down Expand Up @@ -236,8 +242,6 @@ export default class Provisioner {
}
const logsTable = '__logs';
const metadataTable = '__metadata';
const permissionsToAdd: HasuraPermission[] = ['select', 'insert', 'update', 'delete'];
let provisioningComplete = false;

await wrapError(
async () => {
Expand All @@ -251,18 +255,38 @@ export default class Provisioner {
await this.createMetadataTable(indexerConfig.databaseName(), indexerConfig.schemaName());
tableNames.push(metadataTable);
}
},
'Failed logs and metadata provisioning'
);

this.#hasLogsMetadataBeenProvisioned[indexerConfig.accountId] ??= {};
this.#hasLogsMetadataBeenProvisioned[indexerConfig.accountId][indexerConfig.functionName] = true;
}

/**
* Tracks and adds permissions to any Postgres tables successfully created in schema and which lack tracking and/or permissions.
*
* */
async ensureConsistentHasuraState (indexerConfig: IndexerConfig): Promise<void> {
if (this.#hasuraConsistentState[indexerConfig.accountId]?.[indexerConfig.functionName]) {
return;
}
await wrapError(
async () => {
const tableNamesToCheck = await this.getTableNames(indexerConfig.schemaName(), indexerConfig.databaseName());
const permissionsToAdd: HasuraPermission[] = ['select', 'insert', 'update', 'delete'];

const hasuraTablesMetadata = await this.getTrackedTablesWithPermissions(indexerConfig);
const untrackedTables = this.getUntrackedTables(tableNames, hasuraTablesMetadata);
const untrackedTables = this.getUntrackedTables(tableNamesToCheck, hasuraTablesMetadata);
const tablesWithoutPermissions = this.getTablesWithoutPermissions(
indexerConfig.hasuraRoleName(),
tableNames,
tableNamesToCheck,
hasuraTablesMetadata,
permissionsToAdd
);

if (untrackedTables.length === 0 && tablesWithoutPermissions.length === 0) {
provisioningComplete = true;
this.setConsistentState(indexerConfig.accountId, indexerConfig.functionName);
} else {
if (untrackedTables.length > 0) {
await this.trackTables(indexerConfig.schemaName(), untrackedTables, indexerConfig.databaseName());
Expand All @@ -271,14 +295,7 @@ export default class Provisioner {
await this.addPermissionsToTables(indexerConfig, tablesWithoutPermissions, permissionsToAdd);
}
}
},
'Failed logs and metadata provisioning'
);

if (provisioningComplete) {
this.#hasLogsMetadataBeenProvisioned[indexerConfig.accountId] ??= {};
this.#hasLogsMetadataBeenProvisioned[indexerConfig.accountId][indexerConfig.functionName] = true;
}
}, 'Failed to ensure consistent Hasura state');
}

async getTrackedTablesWithPermissions (indexerConfig: IndexerConfig): Promise<TrackedTablePermissions> {
Expand Down

0 comments on commit d0f7fb2

Please sign in to comment.