@effectstream/runtime 0.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +34 -0
- package/src/api/http-server.ts +942 -0
- package/src/api/pagination.ts +456 -0
- package/src/api/rpc-evm/eip1193.ts +920 -0
- package/src/api/rpc-evm/rpc-payloads.ts +297 -0
- package/src/api/rpc-evm/rpc-types.ts +87 -0
- package/src/api/rpc-evm/rpc-utils.ts +50 -0
- package/src/config-snapshot.ts +192 -0
- package/src/main.ts +317 -0
- package/src/mod.ts +3 -0
- package/src/process-blocks.ts +302 -0
- package/src/telemetry.ts +37 -0
- package/src/types.ts +76 -0
- package/src/version-migrations.ts +163 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Operation } from "effection";
|
|
2
|
+
import type { SyncProtocolWithNetwork } from "@effectstream/config";
|
|
3
|
+
import type { AppEvents, BaseStfInput, BaseStfOutput, Primitive } from "@effectstream/sm";
|
|
4
|
+
import type { FastifyInstance } from "fastify";
|
|
5
|
+
import type { Pool } from "pg";
|
|
6
|
+
import type { SnapshotConfig } from "@effectstream/db";
|
|
7
|
+
import type { SyncStateUpdateStream } from "@effectstream/coroutine";
|
|
8
|
+
import type { GrammarDefinition } from "@effectstream/concise";
|
|
9
|
+
// These are user type defined objects for launching the Effectstream Node.
|
|
10
|
+
|
|
11
|
+
export type VERSION = `${number}.${number}.${number}`;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Type for the game state transitions function.
|
|
15
|
+
* For each `prefix` it can return a list of state transitions and events.
|
|
16
|
+
*/
|
|
17
|
+
export type StartConfigGameStateTransitions = (
|
|
18
|
+
blockHeight: number,
|
|
19
|
+
input: BaseStfInput,
|
|
20
|
+
) => SyncStateUpdateStream<void>;
|
|
21
|
+
|
|
22
|
+
export type DBMigrations = {
|
|
23
|
+
versionDependency?: VERSION;
|
|
24
|
+
blockHeight?: number;
|
|
25
|
+
name: string;
|
|
26
|
+
sql: string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Type for the API router function.
|
|
31
|
+
* It should return a valid Fastify instance.
|
|
32
|
+
*/
|
|
33
|
+
export type StartConfigApiRouter = (
|
|
34
|
+
server: FastifyInstance,
|
|
35
|
+
dbConn: Pool,
|
|
36
|
+
) => Promise<void>;
|
|
37
|
+
|
|
38
|
+
export type PrimitiveConstructor<T extends Primitive<any, any>> = new (config: any) => T;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Main configuration object for the Effectstream Node.
|
|
42
|
+
*
|
|
43
|
+
* @param syncInfo - The Networks/Primitives Sync information.
|
|
44
|
+
* @param gameStateTransitions - (optional) Game State Transition Router.
|
|
45
|
+
* @param migrationRouter - (optional) SQL Migrations Router.
|
|
46
|
+
* @param apiRouter - (optional) API Router.
|
|
47
|
+
* @param snapshotConfig - (optional) Automated database snapshot configuration.
|
|
48
|
+
* @param dev - (optional) Development-only configuration.
|
|
49
|
+
* @param dev.resetPublicData - (optional) With this flag, the public schema tables data will be reset on sync process reset. This is useful for testing purposes.
|
|
50
|
+
|
|
51
|
+
*/
|
|
52
|
+
export type StartConfig = {
|
|
53
|
+
appName: string;
|
|
54
|
+
appVersion: VERSION;
|
|
55
|
+
syncInfo: SyncProtocolWithNetwork[];
|
|
56
|
+
gameStateTransitions?: StartConfigGameStateTransitions;
|
|
57
|
+
migrations?: DBMigrations[];
|
|
58
|
+
apiRouter?: StartConfigApiRouter;
|
|
59
|
+
grammar?: GrammarDefinition;
|
|
60
|
+
userDefinedPrimitives?: Record<string, PrimitiveConstructor<any>>;
|
|
61
|
+
/**
|
|
62
|
+
* Automated database snapshot configuration via `pg_dump`.
|
|
63
|
+
* An empty object `{}` enables snapshots with all defaults.
|
|
64
|
+
*
|
|
65
|
+
* Env overrides: `EFFECTSTREAM_SNAPSHOT_INTERVAL_SECONDS`, `EFFECTSTREAM_SNAPSHOT_PATH`,
|
|
66
|
+
* `EFFECTSTREAM_SNAPSHOT_LAST_DAY_HOURLY`, `EFFECTSTREAM_SNAPSHOT_LAST_3_DAYS_SIX_HOURLY`,
|
|
67
|
+
* `EFFECTSTREAM_SNAPSHOT_LAST_N_DAYS`.
|
|
68
|
+
* @see docs/home/1000-effectstream-engine/1003-database-snapshots.md
|
|
69
|
+
*/
|
|
70
|
+
snapshotConfig?: SnapshotConfig;
|
|
71
|
+
/** Development-only options. Do not use in production. */
|
|
72
|
+
dev?: {
|
|
73
|
+
/** Reset public-schema tables on each sync reset. For local testing only. */
|
|
74
|
+
resetPublicData?: boolean;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import type { Client } from "pg";
|
|
2
|
+
import {
|
|
3
|
+
applyMigrations,
|
|
4
|
+
getMigrations,
|
|
5
|
+
EFFECTSTREAM_ENGINE_VERSION,
|
|
6
|
+
parseVersion,
|
|
7
|
+
type VersionInfo,
|
|
8
|
+
} from "@effectstream/db/version";
|
|
9
|
+
import type { Operation } from "effection";
|
|
10
|
+
import { until } from "effection";
|
|
11
|
+
import {
|
|
12
|
+
getMigrationsForBlockHeight,
|
|
13
|
+
insertPaimaEngineVersion,
|
|
14
|
+
} from "@effectstream/db";
|
|
15
|
+
import type { DBMigrations, VERSION } from "@effectstream/runtime";
|
|
16
|
+
|
|
17
|
+
type SystemMigration = {
|
|
18
|
+
version: VERSION;
|
|
19
|
+
sql: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function* applySystemMigrations(
|
|
23
|
+
appVersion: VERSION,
|
|
24
|
+
versionInfo: VersionInfo,
|
|
25
|
+
lastBlockHeight: number,
|
|
26
|
+
dbConn: Client,
|
|
27
|
+
migrationOrder: DBMigrations[] | undefined,
|
|
28
|
+
): Operation<void> {
|
|
29
|
+
if (
|
|
30
|
+
versionInfo.engine_current_version === versionInfo.engine_previous_version
|
|
31
|
+
) {
|
|
32
|
+
console.log("[MIGRATIONS] Nothing to apply.");
|
|
33
|
+
// Nothing to apply.
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const migrations = yield* getAllSystemMigrations(
|
|
38
|
+
versionInfo,
|
|
39
|
+
migrationOrder,
|
|
40
|
+
dbConn as any, // Client,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
// Apply all missing System Migrations
|
|
44
|
+
for (const migration of migrations) {
|
|
45
|
+
yield* until(
|
|
46
|
+
applyMigrations(
|
|
47
|
+
dbConn,
|
|
48
|
+
lastBlockHeight,
|
|
49
|
+
migration.version,
|
|
50
|
+
migration.sql,
|
|
51
|
+
true,
|
|
52
|
+
),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Update Engine Version
|
|
57
|
+
const engineVersion = parseVersion(versionInfo.engine_current_version);
|
|
58
|
+
const appVersionParts = parseVersion(appVersion);
|
|
59
|
+
yield* until(
|
|
60
|
+
insertPaimaEngineVersion.run(
|
|
61
|
+
{
|
|
62
|
+
appVersionMajor: appVersionParts[0],
|
|
63
|
+
appVersionMinor: appVersionParts[1],
|
|
64
|
+
appVersionPatch: appVersionParts[2],
|
|
65
|
+
engineVersionMajor: engineVersion[0],
|
|
66
|
+
engineVersionMinor: engineVersion[1],
|
|
67
|
+
engineVersionPatch: engineVersion[2],
|
|
68
|
+
blockHeight: lastBlockHeight,
|
|
69
|
+
},
|
|
70
|
+
dbConn,
|
|
71
|
+
),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
function* getAllSystemMigrations(
|
|
77
|
+
config: VersionInfo,
|
|
78
|
+
migrationOrder: DBMigrations[] | undefined,
|
|
79
|
+
blockHeight: number,
|
|
80
|
+
): Operation<SystemMigration[]> {
|
|
81
|
+
const fromVersion = config.is_empty
|
|
82
|
+
? undefined
|
|
83
|
+
: config.engine_previous_version;
|
|
84
|
+
const toVersion = config.engine_current_version;
|
|
85
|
+
|
|
86
|
+
// Get System Migrations
|
|
87
|
+
const systemMigrations = fromVersion !== toVersion
|
|
88
|
+
? yield* until(getMigrations(fromVersion, toVersion))
|
|
89
|
+
: [];
|
|
90
|
+
|
|
91
|
+
return systemMigrations;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function* applyUserMigrations(
|
|
95
|
+
currentBlockHeight: number,
|
|
96
|
+
dbConn: Client,
|
|
97
|
+
migrationOrder: DBMigrations[] | undefined,
|
|
98
|
+
): Operation<void> {
|
|
99
|
+
const migrations = yield* getAllUserMigrations(
|
|
100
|
+
EFFECTSTREAM_ENGINE_VERSION,
|
|
101
|
+
migrationOrder,
|
|
102
|
+
currentBlockHeight,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Apply all missing User Migrations
|
|
106
|
+
for (const migration of migrations) {
|
|
107
|
+
yield* until(
|
|
108
|
+
applyMigrations(
|
|
109
|
+
dbConn,
|
|
110
|
+
currentBlockHeight,
|
|
111
|
+
migration.name,
|
|
112
|
+
migration.sql,
|
|
113
|
+
false,
|
|
114
|
+
),
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function* getAllUserMigrations(
|
|
120
|
+
currentEngineVersion: VERSION,
|
|
121
|
+
migrationOrder: DBMigrations[] | undefined,
|
|
122
|
+
blockHeight: number,
|
|
123
|
+
): Operation<DBMigrations[]> {
|
|
124
|
+
// Get User Migrations
|
|
125
|
+
const userMigrations = getMigrationsForBlockHeight(
|
|
126
|
+
migrationOrder,
|
|
127
|
+
blockHeight,
|
|
128
|
+
blockHeight,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// Check if User Migrations are compatible with the current version
|
|
132
|
+
for (const migration of userMigrations) {
|
|
133
|
+
// If a current version is provided we check if the migration have the correct version dependency
|
|
134
|
+
if (migration.versionDependency) {
|
|
135
|
+
if (
|
|
136
|
+
!isVersionGreaterOrEqual(
|
|
137
|
+
currentEngineVersion,
|
|
138
|
+
migration.versionDependency,
|
|
139
|
+
)
|
|
140
|
+
) {
|
|
141
|
+
throw new Error(`[CRITICAL ERROR] Migration ${migration.name} failed.
|
|
142
|
+
Paima Engine Version ${migration.versionDependency} required.
|
|
143
|
+
Current version ${currentEngineVersion} is not compatible.
|
|
144
|
+
Please update your Paima Engine dependencies.`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return userMigrations;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function isVersionGreaterOrEqual(
|
|
153
|
+
version: VERSION,
|
|
154
|
+
migrationVersion: VERSION,
|
|
155
|
+
): boolean {
|
|
156
|
+
const versionParts = parseVersion(version);
|
|
157
|
+
const migrationVersionParts = parseVersion(migrationVersion);
|
|
158
|
+
return (
|
|
159
|
+
versionParts[0] > migrationVersionParts[0] ||
|
|
160
|
+
(versionParts[0] === migrationVersionParts[0] &&
|
|
161
|
+
versionParts[1] >= migrationVersionParts[1])
|
|
162
|
+
);
|
|
163
|
+
}
|