Skip to content

Commit

Permalink
feat: Cache parsed SQL in Event class
Browse files Browse the repository at this point in the history
This reduces the number of times we need to parse the SQL, which is
expensive, and improves sequence diagram load times by ~24%
  • Loading branch information
ahtrotta committed Oct 5, 2023
1 parent f0ede48 commit 5d6f222
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
19 changes: 15 additions & 4 deletions packages/models/src/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ function alias(obj, prop, alias) {
// This class supercedes `CallTree` and `CallNode`. Events are stored in a flat
// array and can also be traversed like a tree via `parent` and `children`.
export default class Event {
static parsedSqlCache = {};

static contentType(...messages) {
const msg = messages.find((message) => (message?.headers || {})['Content-Type']);
if (!msg) {
Expand Down Expand Up @@ -526,10 +528,19 @@ export default class Event {

let properties;
if (sqlQuery) {
const sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
.join(`{"type":"variable"}`);
let sqlNormalized;
const cacheKey = `${this.sql.database_type}:${sqlQuery}`;
if (!Event.parsedSqlCache[cacheKey]) {
sqlNormalized = abstractSqlAstJSON(sqlQuery, this.sql.database_type)
// Collapse repeated variable literals and parameter tokens (e.g. '?, ?' in an IN clause)
.split(/{"type":"variable"}(?:,{"type":"variable"})*/g)
.join(`{"type":"variable"}`);

Event.parsedSqlCache[cacheKey] = sqlNormalized;
} else {
sqlNormalized = Event.parsedSqlCache[cacheKey];
}

properties = {
event_type: 'sql',
sql_normalized: sqlNormalized,
Expand Down
15 changes: 12 additions & 3 deletions packages/models/tests/unit/event.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,21 @@ describe('Event', () => {
});
});
describe('stableProperties', () => {
it('sql_normalized', () => {
it('sql_normalized and cached', () => {
const expectedSqlNormalized =
'{"type":"statement","variant":"list","statement":[{"type":"statement","variant":"select","result":[{"type":"function","name":{"type":"identifier","variant":"function","name":"count"},"args":{"type":"identifier","variant":"star","name":"*"}}],"from":{"type":"identifier","variant":"table","name":"spree_stores"}}]}';

verifyJSON(sqlEvent.gatherStableProperties(), {
event_type: 'sql',
sql_normalized:
'{"type":"statement","variant":"list","statement":[{"type":"statement","variant":"select","result":[{"type":"function","name":{"type":"identifier","variant":"function","name":"count"},"args":{"type":"identifier","variant":"star","name":"*"}}],"from":{"type":"identifier","variant":"table","name":"spree_stores"}}]}',
sql_normalized: expectedSqlNormalized,
});

const expectedSqlKey = `${sqlEvent.sql.database_type}:${sqlEvent.sqlQuery}`;
const expectedSqlCache = {
[expectedSqlKey]: expectedSqlNormalized,
};

expect(Event.parsedSqlCache).toEqual(expectedSqlCache);
});
it('sql_normalized with query parameters', () => {
const sql = {
Expand Down

0 comments on commit 5d6f222

Please sign in to comment.