Skip to content

Commit a00a9a5

Browse files
committed
feat: cache query counts
1 parent 9670f71 commit a00a9a5

16 files changed

Lines changed: 591 additions & 29 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "krist",
3-
"version": "3.5.6",
3+
"version": "3.5.7",
44
"description": "The new Krist node written in TypeScript.",
55
"type": "module",
66
"scripts": {

src/controllers/names.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { verifyAddress } from "../krist/addresses/verify.js";
3838
import { createName, getName, getNames, getNamesByAddress, getUnpaidNames } from "../krist/names/index.js";
3939
import { areTransactionsEnabled } from "../krist/switches.js";
4040
import { createTransaction, logTransaction, pushTransaction } from "../krist/transactions/create.js";
41+
import { invalidateCountCache } from "../utils/cache.js";
4142
import { isValidARecord, isValidKristAddress, isValidName, validateLimitOffset } from "../utils/index.js";
4243
import { checkTxRateLimits } from "../utils/rateLimit.js";
4344
import { NAME_COST } from "../utils/vars.js";
@@ -220,6 +221,11 @@ export async function ctrlTransferName(
220221
null,
221222
dbName.name
222223
);
224+
225+
dbTx.afterCommit(async () => {
226+
// Invalidate name count caches (owner changed)
227+
await invalidateCountCache(Name.name);
228+
});
223229
});
224230

225231
// Return the updated name
@@ -285,6 +291,11 @@ export async function ctrlUpdateName(
285291
dbName.name,
286292
a
287293
);
294+
295+
dbTx.afterCommit(async () => {
296+
// Invalidate name count caches (A-record changed)
297+
await invalidateCountCache(Name.name);
298+
});
288299
});
289300

290301
// Return the updated name

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { initDatabase, shutdownDb } from "./database/index.js";
2727
import { initRedis, shutdownRedis } from "./database/redis.js";
2828
import { initAuthLogCleanup, shutdownAuthLogCleanup } from "./krist/authLog.js";
2929
import { initKrist } from "./krist/index.js";
30+
import { stopAllAutomaticCacheInvalidation } from "./utils/cache.js";
3031
import { initWorkOverTime, shutdownWorkOverTime } from "./krist/work.js";
3132
import { initCriticalLogUpdater } from "./utils/criticalLog.js";
3233

@@ -53,6 +54,7 @@ async function main() {
5354
function shutdown() {
5455
(async () => {
5556
shutdownWebserver();
57+
stopAllAutomaticCacheInvalidation();
5658
await shutdownRedis();
5759
await shutdownDb();
5860
shutdownWorkOverTime();

src/krist/addresses/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import { QueryTypes } from "@sequelize/core";
2323
import { Address, db, Limit, Offset, PaginatedResult } from "../../database/index.js";
24+
import { cachedFindAndCountAll } from "../../utils/cache.js";
2425
import { sanitiseLimit, sanitiseOffset } from "../../utils/index.js";
2526

2627
export interface AddressWithNames extends Address {
@@ -64,7 +65,7 @@ export async function getAddresses(
6465
limit?: Limit,
6566
offset?: Offset
6667
): Promise<PaginatedResult<Address>> {
67-
return Address.findAndCountAll({
68+
return cachedFindAndCountAll(Address, {
6869
limit: sanitiseLimit(limit),
6970
offset: sanitiseOffset(offset)
7071
});
@@ -74,7 +75,7 @@ export async function getRichAddresses(
7475
limit?: Limit,
7576
offset?: Offset
7677
): Promise<PaginatedResult<Address>> {
77-
return Address.findAndCountAll({
78+
return cachedFindAndCountAll(Address, {
7879
order: [["balance", "DESC"]],
7980
limit: sanitiseLimit(limit),
8081
offset: sanitiseOffset(offset)

src/krist/addresses/verify.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import chalkT from "chalk-template";
2323
import { Request } from "express";
2424
import promClient from "prom-client";
2525
import { Address } from "../../database/index.js";
26+
import { invalidateCountCache } from "../../utils/cache.js";
2627
import { criticalLog } from "../../utils/criticalLog.js";
2728
import { getLogDetails, makeV2Address, sha256 } from "../../utils/index.js";
2829
import { logAuth } from "../authLog.js";
@@ -64,6 +65,9 @@ export async function verifyAddress(
6465
privatekey: hash
6566
});
6667

68+
// Invalidate address count caches (new address created)
69+
await invalidateCountCache(Address.name);
70+
6771
logAuth(req, kristAddress, "auth").catch(console.error);
6872
promAddressesVerifiedCounter.inc({ type: "authed" });
6973
return { authed: true, address: newAddress };

src/krist/blocks/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import { Op } from "@sequelize/core";
4444
import { Block, Limit, Offset, PaginatedResult, SqTransaction } from "../../database/index.js";
45+
import { cachedFindAndCountAll } from "../../utils/cache.js";
4546
import { getBaseBlockValue, getLegacyWork, sanitiseLimit, sanitiseOffset } from "../../utils/index.js";
4647
import { getUnpaidNameCount } from "../names/index.js";
4748

@@ -54,7 +55,7 @@ export async function getBlocks(
5455
offset?: Offset,
5556
asc?: boolean
5657
): Promise<PaginatedResult<Block>> {
57-
return Block.findAndCountAll({
58+
return cachedFindAndCountAll(Block, {
5859
order: [["id", asc ? "ASC" : "DESC"]],
5960
limit: sanitiseLimit(limit),
6061
offset: sanitiseOffset(offset)
@@ -74,10 +75,10 @@ export async function getLowestHashes(
7475
limit?: Limit,
7576
offset?: Offset
7677
): Promise<PaginatedResult<Block>> {
77-
return Block.findAndCountAll({
78+
return cachedFindAndCountAll(Block, {
7879
where: {
7980
[Op.and]: [
80-
{ hash: { [Op.not]: null } },
81+
{ hash: { [Op.isNot]: null } },
8182
{ id: { [Op.gt]: 10 } } // Ignore the genesis block
8283
]
8384
},

src/krist/blocks/lookup.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import { InferAttributes, Order, sql } from "@sequelize/core";
2323
import { Block, Limit, Offset, PaginatedResult } from "../../database/index.js";
24+
import { cachedFindAndCountAll } from "../../utils/cache.js";
2425
import { sanitiseLimit, sanitiseOffset } from "../../utils/index.js";
2526

2627
export async function lookupBlocks(
@@ -38,7 +39,7 @@ export async function lookupBlocks(
3839
? [sql`ISNULL(hash)`, ["hash", "ASC"]]
3940
: [[orderBy, order]];
4041

41-
return Block.findAndCountAll({
42+
return cachedFindAndCountAll(Block, {
4243
order: dbOrder,
4344
limit: sanitiseLimit(limit),
4445
offset: sanitiseOffset(offset),

src/krist/blocks/submit.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { Request } from "express";
2626
import promClient from "prom-client";
2727
import { Address, Block, db, Name } from "../../database/index.js";
2828
import { ErrorMiningDisabled, ErrorSolutionDuplicate, ErrorSolutionIncorrect } from "../../errors/index.js";
29+
import { invalidateCountCache } from "../../utils/cache.js";
2930
import { getLogDetails, sha256 } from "../../utils/index.js";
3031
import { MAX_WORK, MIN_WORK, SECONDS_PER_BLOCK, WORK_FACTOR } from "../../utils/vars.js";
3132
import { wsManager } from "../../websockets/index.js";
@@ -164,6 +165,11 @@ export async function createBlock(
164165
totalin: value,
165166
totalout: 0
166167
}, { transaction: dbTx });
168+
169+
dbTx.afterCommit(async () => {
170+
// Invalidate address count caches (new address created)
171+
await invalidateCountCache(Address.name);
172+
});
167173
}
168174

169175
return {
@@ -180,6 +186,9 @@ export async function createBlock(
180186
console.log(chalkT` New work: {green ${retWork.toLocaleString()}} New balance: {green ${retAddress.balance}}`);
181187
await setWork(retWork);
182188

189+
// Invalidate block count caches
190+
await invalidateCountCache(Block.name);
191+
183192
// Submit the new block event to all websockets (async)
184193
wsManager.broadcastEvent({
185194
type: "event",

src/krist/names/index.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { Op, QueryTypes, sql } from "@sequelize/core";
2323

2424
import promClient from "prom-client";
2525
import { db, Limit, Name, Offset, PaginatedResult, SqTransaction } from "../../database/index.js";
26-
26+
import { cachedFindAndCountAll, cachedCount, invalidateCountCache } from "../../utils/cache.js";
2727
import { sanitiseLimit, sanitiseOffset } from "../../utils/index.js";
2828
import { NAME_COST } from "../../utils/vars.js";
2929

@@ -38,7 +38,7 @@ export async function getNames(
3838
limit?: Limit,
3939
offset?: Offset
4040
): Promise<PaginatedResult<Name>> {
41-
return Name.findAndCountAll({
41+
return cachedFindAndCountAll(Name, {
4242
order: [["name", "ASC"]],
4343
limit: sanitiseLimit(limit),
4444
offset: sanitiseOffset(offset)
@@ -50,7 +50,7 @@ export async function getNamesByAddress(
5050
limit?: Limit,
5151
offset?: Offset
5252
): Promise<PaginatedResult<Name>> {
53-
return Name.findAndCountAll({
53+
return cachedFindAndCountAll(Name, {
5454
order: [["name", "ASC"]],
5555
where: { owner: address },
5656
limit: sanitiseLimit(limit),
@@ -72,7 +72,7 @@ export async function getDetailedUnpaid(): Promise<DetailedUnpaidResponseRow[]>
7272
}
7373

7474
export async function getNameCountByAddress(address: string): Promise<number> {
75-
return Name.count({ where: { owner: address }});
75+
return cachedCount(Name, { where: { owner: address }});
7676
}
7777

7878
export async function getName(name: string): Promise<Name | null> {
@@ -83,7 +83,7 @@ export async function getUnpaidNames(
8383
limit?: Limit,
8484
offset?: Offset
8585
): Promise<PaginatedResult<Name>> {
86-
return Name.findAndCountAll({
86+
return cachedFindAndCountAll(Name, {
8787
order: [["id", "DESC"]],
8888
where: { unpaid: { [Op.gt]: 0 }},
8989
limit: sanitiseLimit(limit),
@@ -115,12 +115,17 @@ export async function createName(
115115
unpaid: NAME_COST
116116
}, { transaction: dbTx });
117117

118-
promNamesPurchasedCounter.inc();
118+
dbTx.afterCommit(async () => {
119+
promNamesPurchasedCounter.inc();
120+
121+
// Invalidate name count caches
122+
await invalidateCountCache(Name.name);
119123

120-
wsManager.broadcastEvent({
121-
type: "event",
122-
event: "name",
123-
name: nameToJson(dbName)
124+
wsManager.broadcastEvent({
125+
type: "event",
126+
event: "name",
127+
name: nameToJson(dbName)
128+
});
124129
});
125130

126131
return dbName;

src/krist/names/lookup.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import { InferAttributes, Op, sql } from "@sequelize/core";
2323
import { Limit, Name, Offset, PaginatedResult } from "../../database/index.js";
24+
import { cachedFindAndCountAll } from "../../utils/cache.js";
2425
import { sanitiseLimit, sanitiseOffset } from "../../utils/index.js";
2526

2627
export async function lookupNames(
@@ -30,7 +31,7 @@ export async function lookupNames(
3031
orderBy: (keyof InferAttributes<Name>) | "transferredOrRegistered" = "name",
3132
order: "ASC" | "DESC" = "ASC"
3233
): Promise<PaginatedResult<Name>> {
33-
return Name.findAndCountAll({
34+
return cachedFindAndCountAll(Name, {
3435
order: [[
3536
// Ordering by `transferred` can return null results and may not be the desirable ordering for the user, so
3637
// `transferredOrRegistered` is an alternative option that falls back to `registered` if `transferred` is null.

0 commit comments

Comments
 (0)