I am loading some data from a DB table using sequelize and caching it in an in-memory object with a TTL so I don’t keep reading from the DB over and over again.
<code>// ffm.ts
import { Op } from 'sequelize';
import { State } from 'src/db/models/geo/state';
export class FFMStates {
private static lastRefreshed = new Date(0); // Initialize to start of epoch
private static TTL = 60 * 60; // 1 hour
public static DATA: Record<number, Array<string>>;
public static async load() {
FFMStates.lastRefreshed = new Date();
const currentYear = FFMStates.lastRefreshed.getFullYear();
const results = await State.findAll({
where: {
year: { [Op.gte]: currentYear - 2 }, // load 3 or 4 latest years
ffm: true,
},
order: [
['year', 'ASC'],
['code', 'ASC'],
],
});
FFMStates.DATA = results.reduce((acc: Record<number, string[]>, state) => {
if (!acc[state.year]) {
acc[state.year] = [];
}
acc[state.year].push(state.code);
return acc;
}, {});
}
public static async get() {
if ((new Date().getTime() - FFMStates.lastRefreshed.getTime()) / 1000 > FFMStates.TTL) {
await FFMStates.load();
}
return FFMStates.DATA;
}
}
</code>
<code>// ffm.ts
import { Op } from 'sequelize';
import { State } from 'src/db/models/geo/state';
export class FFMStates {
private static lastRefreshed = new Date(0); // Initialize to start of epoch
private static TTL = 60 * 60; // 1 hour
public static DATA: Record<number, Array<string>>;
public static async load() {
FFMStates.lastRefreshed = new Date();
const currentYear = FFMStates.lastRefreshed.getFullYear();
const results = await State.findAll({
where: {
year: { [Op.gte]: currentYear - 2 }, // load 3 or 4 latest years
ffm: true,
},
order: [
['year', 'ASC'],
['code', 'ASC'],
],
});
FFMStates.DATA = results.reduce((acc: Record<number, string[]>, state) => {
if (!acc[state.year]) {
acc[state.year] = [];
}
acc[state.year].push(state.code);
return acc;
}, {});
}
public static async get() {
if ((new Date().getTime() - FFMStates.lastRefreshed.getTime()) / 1000 > FFMStates.TTL) {
await FFMStates.load();
}
return FFMStates.DATA;
}
}
</code>
// ffm.ts
import { Op } from 'sequelize';
import { State } from 'src/db/models/geo/state';
export class FFMStates {
private static lastRefreshed = new Date(0); // Initialize to start of epoch
private static TTL = 60 * 60; // 1 hour
public static DATA: Record<number, Array<string>>;
public static async load() {
FFMStates.lastRefreshed = new Date();
const currentYear = FFMStates.lastRefreshed.getFullYear();
const results = await State.findAll({
where: {
year: { [Op.gte]: currentYear - 2 }, // load 3 or 4 latest years
ffm: true,
},
order: [
['year', 'ASC'],
['code', 'ASC'],
],
});
FFMStates.DATA = results.reduce((acc: Record<number, string[]>, state) => {
if (!acc[state.year]) {
acc[state.year] = [];
}
acc[state.year].push(state.code);
return acc;
}, {});
}
public static async get() {
if ((new Date().getTime() - FFMStates.lastRefreshed.getTime()) / 1000 > FFMStates.TTL) {
await FFMStates.load();
}
return FFMStates.DATA;
}
}
I am then using this module as follows:
<code>import { FFMStates } from 'src/constants/health/ffm';
const ffmStates = await FFMStates.get();
const currentYear = ffmStates[this.year]; // This throws an error the first time this code runs because ffmStates is undefined
</code>
<code>import { FFMStates } from 'src/constants/health/ffm';
const ffmStates = await FFMStates.get();
const currentYear = ffmStates[this.year]; // This throws an error the first time this code runs because ffmStates is undefined
</code>
import { FFMStates } from 'src/constants/health/ffm';
const ffmStates = await FFMStates.get();
const currentYear = ffmStates[this.year]; // This throws an error the first time this code runs because ffmStates is undefined
I tried debugging this with console.log()
statements. It seems that when FFMStates.get()
is called the first time, my code starts to run FFMStates.load()
but does not await it and immediately executes the next line after the if block
and returns FFMStates.DATA
which is undefined at this point. I am not sure why await FFMStates.load()
does not wait.