Skip to content

Commit a6191e7

Browse files
Copilothotlong
andcommitted
feat: Add 8 kernel optimizations for ObjectQL
Implemented the following optimizations: 1. OptimizedMetadataRegistry with O(k) package uninstall 2. QueryCompiler with LRU cache for query plans 3. CompiledHookManager with pre-compiled hook pipelines 4. GlobalConnectionPool with kernel-level pooling 5. OptimizedValidationEngine with compiled validators 6. LazyMetadataLoader with on-demand loading 7. DependencyGraph with DAG-based dependency resolution 8. SQLQueryOptimizer with index hints and join optimization Added comprehensive test suite for all optimizations. Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent a39bb2f commit a6191e7

11 files changed

Lines changed: 2179 additions & 0 deletions

packages/foundation/core/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ export * from './query';
3030
// Export utilities
3131
export * from './util';
3232
export * from './ai-agent';
33+
34+
// Export kernel optimizations
35+
export * from './optimizations';
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/**
2+
* ObjectQL
3+
* Copyright (c) 2026-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
/**
10+
* Hook definition
11+
*/
12+
export interface Hook {
13+
pattern: string;
14+
handler: (context: any) => Promise<void> | void;
15+
packageName?: string;
16+
priority?: number;
17+
}
18+
19+
/**
20+
* Compiled Hook Manager
21+
*
22+
* Improvement: Pre-compiles hook pipelines by event pattern at registration time.
23+
* No runtime pattern matching required.
24+
*
25+
* Expected: 5x faster hook execution, parallel async support
26+
*/
27+
export class CompiledHookManager {
28+
// Direct event -> hooks mapping (no pattern matching at runtime)
29+
private pipelines = new Map<string, Hook[]>();
30+
31+
// Keep track of all registered hooks for management
32+
private allHooks = new Map<string, Hook>();
33+
34+
/**
35+
* Expand a pattern like "before*" to all matching events
36+
*/
37+
private expandPattern(pattern: string): string[] {
38+
// Common event patterns
39+
const eventTypes = [
40+
'beforeCreate', 'afterCreate',
41+
'beforeUpdate', 'afterUpdate',
42+
'beforeDelete', 'afterDelete',
43+
'beforeFind', 'afterFind',
44+
'beforeCount', 'afterCount'
45+
];
46+
47+
// Handle wildcards
48+
if (pattern === '*') {
49+
return eventTypes;
50+
}
51+
52+
if (pattern.includes('*')) {
53+
const regex = new RegExp('^' + pattern.replace('*', '.*') + '$');
54+
return eventTypes.filter(event => regex.test(event));
55+
}
56+
57+
// Exact match
58+
return [pattern];
59+
}
60+
61+
/**
62+
* Register a hook - pre-groups by event pattern
63+
*/
64+
registerHook(event: string, objectName: string, handler: any, packageName?: string): void {
65+
const hook: Hook = {
66+
pattern: `${event}:${objectName}`,
67+
handler,
68+
packageName,
69+
priority: 0
70+
};
71+
72+
// Store in all hooks registry
73+
const hookId = `${event}:${objectName}:${Date.now()}`;
74+
this.allHooks.set(hookId, hook);
75+
76+
// Expand event patterns
77+
const events = this.expandPattern(event);
78+
79+
// Pre-group hooks by concrete event names
80+
for (const concreteEvent of events) {
81+
const key = `${concreteEvent}:${objectName}`;
82+
if (!this.pipelines.has(key)) {
83+
this.pipelines.set(key, []);
84+
}
85+
this.pipelines.get(key)!.push(hook);
86+
}
87+
88+
// Handle wildcard object names
89+
if (objectName === '*') {
90+
for (const concreteEvent of events) {
91+
// Register for all potential object names
92+
// Since we don't know all object names upfront, we keep a special '*' pipeline
93+
const wildcardKey = `${concreteEvent}:*`;
94+
if (!this.pipelines.has(wildcardKey)) {
95+
this.pipelines.set(wildcardKey, []);
96+
}
97+
this.pipelines.get(wildcardKey)!.push(hook);
98+
}
99+
}
100+
}
101+
102+
/**
103+
* Run hooks for an event - direct lookup, no pattern matching
104+
*/
105+
async runHooks(event: string, objectName: string, context: any): Promise<void> {
106+
const key = `${event}:${objectName}`;
107+
const wildcardKey = `${event}:*`;
108+
109+
// Collect all applicable hooks
110+
const hooks: Hook[] = [];
111+
112+
// Add object-specific hooks
113+
const objectHooks = this.pipelines.get(key);
114+
if (objectHooks) {
115+
hooks.push(...objectHooks);
116+
}
117+
118+
// Add wildcard hooks
119+
const wildcardHooks = this.pipelines.get(wildcardKey);
120+
if (wildcardHooks) {
121+
hooks.push(...wildcardHooks);
122+
}
123+
124+
if (hooks.length === 0) {
125+
return;
126+
}
127+
128+
// Sort by priority (higher priority first)
129+
hooks.sort((a, b) => (b.priority || 0) - (a.priority || 0));
130+
131+
// Execute hooks in parallel for better performance
132+
// Note: If order matters, change to sequential execution
133+
await Promise.all(hooks.map(hook => {
134+
try {
135+
return Promise.resolve(hook.handler(context));
136+
} catch (error) {
137+
console.error(`Hook execution failed for ${event}:${objectName}`, error);
138+
return Promise.resolve();
139+
}
140+
}));
141+
}
142+
143+
/**
144+
* Remove all hooks from a package
145+
*/
146+
removePackage(packageName: string): void {
147+
// Remove from all hooks registry
148+
const hooksToRemove: string[] = [];
149+
for (const [hookId, hook] of this.allHooks.entries()) {
150+
if (hook.packageName === packageName) {
151+
hooksToRemove.push(hookId);
152+
}
153+
}
154+
hooksToRemove.forEach(id => this.allHooks.delete(id));
155+
156+
// Remove from pipelines
157+
for (const [key, hooks] of this.pipelines.entries()) {
158+
const filtered = hooks.filter(h => h.packageName !== packageName);
159+
if (filtered.length === 0) {
160+
this.pipelines.delete(key);
161+
} else {
162+
this.pipelines.set(key, filtered);
163+
}
164+
}
165+
}
166+
167+
/**
168+
* Clear all hooks
169+
*/
170+
clear(): void {
171+
this.pipelines.clear();
172+
this.allHooks.clear();
173+
}
174+
175+
/**
176+
* Get statistics about registered hooks
177+
*/
178+
getStats(): { totalHooks: number; totalPipelines: number } {
179+
return {
180+
totalHooks: this.allHooks.size,
181+
totalPipelines: this.pipelines.size
182+
};
183+
}
184+
}

0 commit comments

Comments
 (0)