This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
NEsper is a Complex Event Processing (CEP) engine for .NET, ported from the Java-based Esper. It provides an Event Processing Language (EPL) for querying, analyzing, and processing event streams in real-time.
Build all projects:
dotnet build NEsperAll.slnBuild specific components:
dotnet build src/NEsper.Common/NEsper.Common.csproj
dotnet build src/NEsper.Compiler/NEsper.Compiler.csproj
dotnet build src/NEsper.Runtime/NEsper.Runtime.csprojRun all tests:
dotnet test NEsperAll.slnRun tests for a specific project:
dotnet test tst/NEsper.Common.Tests/NEsper.Common.Tests.csproj
dotnet test tst/NEsper.Compiler.Tests/NEsper.Compiler.Tests.csproj
dotnet test tst/NEsper.Runtime.Tests/NEsper.Runtime.Tests.csproj
dotnet test tst/NEsper.Compat.Tests/NEsper.Compat.Tests.csprojRun a single test by filter:
dotnet test --filter "FullyQualifiedName~TestClassName.TestMethodName"Run tests with specific settings (uses NEsper.runsettings):
dotnet test NEsperAll.sln --settings NEsper.runsettingsRun regression tests:
dotnet test tst/NEsper.Regression.Runner/NEsper.Regression.Runner.csprojNEsper includes a configurable batch test system for efficient regression testing with 3,801 tests:
# View all available test batches and configuration
.\run-test-batches.ps1 -Summary
# Run all regression tests in organized batches
.\run-test-batches.ps1
# Run specific batch for quick feedback
.\run-test-batches.ps1 -BatchName "Client" # ~2.5 min, 253 tests
.\run-test-batches.ps1 -BatchName "EPL-Database" # ~20 sec, 55 tests
# Run with verbose output for debugging
.\run-test-batches.ps1 -BatchName "Event" -Verbose
# Run isolated tests that have state pollution issues
.\run-test-batches.ps1 -IsolatedOnlyConfiguration: Edit test-batches.json to adjust batches, timeouts, and filters.
Documentation:
- QUICK-TEST-GUIDE.md - Quick reference and common commands
- TEST-BATCHES-README.md - Complete documentation
Test Statistics:
- Total Tests: 3,801 regression + 1,890 unit = 5,691 tests
- Pass Rate: 99.87% (4 known XML XPath failures, 4 intermittent isolation issues)
- Frameworks: net8.0, net9.0
Some tests require PostgreSQL. Start the database using:
cd tst/db
docker-compose up -dDatabase credentials:
- Database: esper
- User: esper
- Password: 3sp3rP@ssw0rd
- Port: 5432
NEsper follows a compile-then-deploy architecture with clear separation between compile-time and runtime:
NEsper.Compat - Java compatibility layer
- Provides Java-like collections (LinkedHashMap, LinkedHashSet)
- Threading primitives (CountDownLatch, AtomicLong, ReadWriteLock)
- Cross-platform utilities and time handling
- Located in:
src/NEsper.Compat/
NEsper.Common - Shared compile-time and runtime infrastructure
- Event type system (EventBean, EventType, property accessors)
- Bytecode generation model for code generation
- Compilation stages (stage1, stage2, stage3)
- EPL language features (expressions, patterns, aggregations, joins, windows)
- Filter specifications and evaluation
- Located in:
src/NEsper.Common/ - Root namespace:
com.espertech.esper.common
NEsper.Grammar - ANTLR grammar for EPL parsing
- Contains ANTLR4 grammar files
- Generated parser and lexer for EPL syntax
- Located in:
src/NEsper.Grammar/
NEsper.Compiler - EPL compilation to .NET assemblies
- Entry point:
EPCompilerProvider.Compiler - Parses EPL text into AST using ANTLR
- 3-stage compilation pipeline
- Generates C# code using Roslyn
- Outputs
EPCompiledartifacts containing .NET assemblies - Located in:
src/NEsper.Compiler/
NEsper.Runtime - Event processing runtime engine
- Entry point:
EPRuntimeProvider.GetDefaultRuntime() - Deploys compiled EPL modules
- Processes incoming events
- Manages filter service, scheduler, variables, contexts
- Delivers results to listeners
- Located in:
src/NEsper.Runtime/
Optional Components:
- NEsper.Avro - Apache Avro event format support
- NEsper.IO - Input/output adapters
- NEsper.Data.* - Database drivers (MySQL, PostgreSQL, SQLite, SQLServer, ODBC)
- NEsper.Scripting.* - Scripting engine integration (ClearScript, Jurassic)
- NEsper.Log.NLog - NLog integration
Stage 1 - Parse & Validate (common/internal/compile/stage1/)
- Parse EPL text using ANTLR grammar
- Build statement specification (StatementSpec)
- Basic syntax validation
Stage 2 - Semantic Analysis (common/internal/compile/stage2/)
- Type checking and resolution
- Build filter specifications (FilterSpecCompiled)
- Create compiled specifications (StatementSpecCompiled)
- Validate semantics against event types
Stage 3 - Code Generation (common/internal/compile/stage3/)
- Generate "forge" descriptors for code generation
- Create StatementAIFactoryProvider classes
- Build CodegenClass model representing C# code
- Generate C# source using Roslyn SyntaxFactory
- Compile to .NET assemblies using Roslyn
- Package as EPCompiled with manifest
Deployment:
- Load compiled assemblies from EPCompiled artifact
- Instantiate ModuleProvider classes
- Initialize EPL objects (event types, variables, named windows, contexts)
- Create StatementAIFactoryProvider instances
- Register with deployment lifecycle service
Statement Activation:
- StatementAIFactoryProvider creates StatementAgentInstanceFactory
- Factory creates statement resources (filters, views, aggregations)
- Register with filter service and schedule service
- Attach update listeners/subscribers
Event Processing:
- Events sent via
EPEventService.SendEvent() - Wrapped as EventBean
- Filter service evaluates using index-based matching
- Matching statements receive events
- Events flow through view chain (windows, patterns, aggregations)
- Result set processing produces output
- UpdateListener callbacks invoked with results
NEsper uses code generation instead of interpretation for maximum performance:
Why Code Generation:
- Generated code runs at native .NET speed (no interpretation overhead)
- Full Roslyn optimization applies
- Type-safe compiled expressions
- Debuggable generated code
Key Generated Classes:
StatementAIFactoryProvider- Factory for statement instancesStatementProvider- Statement metadata- Expression evaluators - Compiled EPL expressions
- Event property getters - Fast property access
- Filter evaluators - WHERE clause evaluation
- Aggregation functions - Compiled aggregation logic
Codegen Model: (common/internal/bytecodemodel/)
CodegenClass- Represents a C# classCodegenMethod- Represents a method with parameters and bodyCodegenExpression- Type-safe expression DSLCodeGenerationHelper- Converts CodegenClass to Roslyn SyntaxTree
Forge Pattern:
- Compile-time "forge" objects create runtime instances
- Example:
FilterSpecParamForgecreates runtime evaluator - Separation between compile-time description and runtime execution
Factory Pattern:
StatementAIFactoryProvidercreates statement instances- Allows multiple statement instances per context partition
- Encapsulates statement initialization logic
Service Locator (being removed):
EPServicesContextprovides centralized access to runtime services- Active refactoring: eliminating IContainer as a runtime service locator — see
.planning/service-locator-removal/PLAN.md
Event-Driven:
- Asynchronous event processing
- Listener/observer pattern for result delivery
- Filter service uses index structures for efficient matching
Path/Repository:
- Compiled modules reference each other through path mechanism
- Supports modular EPL deployments
- Named windows, variables, tables can be shared across modules
All NEsper code uses Java-style namespaces to maintain compatibility with Java Esper:
- Root namespace:
com.espertech.esper - Example:
com.espertech.esper.common.client.EventBean - This is intentional for cross-platform consistency
Compilation Entry Points:
src/NEsper.Compiler/client/EPCompiler.cs- Public APIsrc/NEsper.Compiler/internal/util/EPCompilerImpl.cs- Main implementation
Runtime Entry Points:
src/NEsper.Runtime/client/EPRuntime.cs- Public APIsrc/NEsper.Runtime/internal/kernel/service/EPRuntimeImpl.cs- Main implementationsrc/NEsper.Runtime/internal/kernel/service/Deployer.cs- Deployment orchestration
Core Abstractions:
src/NEsper.Common/common/client/EventBean.cs- Event wrappersrc/NEsper.Common/common/client/EventType.cs- Event type metadatasrc/NEsper.Common/common/client/EPCompiled.cs- Compiled EPL artifactsrc/NEsper.Common/common/internal/context/module/StatementAIFactoryProvider.cs- Statement factory
Codegen Infrastructure:
src/NEsper.Common/common/internal/bytecodemodel/core/CodegenClass.cs- Class modelsrc/NEsper.Common/common/internal/bytecodemodel/core/CodeGenerationHelper.cs- Roslyn integrationsrc/NEsper.Common/common/internal/bytecodemodel/model/expression/- Expression DSL
Event System:
src/NEsper.Common/common/internal/event/bean/- POCO event representationsrc/NEsper.Common/common/internal/event/map/- Map-based eventssrc/NEsper.Common/common/internal/event/json/- JSON eventssrc/NEsper.Common/common/internal/event/xml/- XML eventssrc/NEsper.Avro/- Avro event representation
Projects target both .NET 8.0 and .NET 9.0 (multi-targeting):
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>Test Framework: NUnit 4.x
Test Projects:
tst/NEsper.Common.Tests/- Unit tests for NEsper.Commontst/NEsper.Compiler.Tests/- Unit tests for NEsper.Compilertst/NEsper.Runtime.Tests/- Unit tests for NEsper.Runtimetst/NEsper.Compat.Tests/- Unit tests for compatibility layertst/NEsper.Regression/- Comprehensive regression test suitetst/NEsper.Regression.Runner/- Runner for regression tests
Test Settings:
NEsper.runsettingsconfigures test execution- Default timeout: 300000ms (5 minutes)
- Uses parallel test workers
- Most exceptions inherit from
EPException(common/client/EPException.cs) - Compile-time exceptions:
EPCompileException - Runtime exceptions:
EPRuntimeException,EPDeployException - Configuration exceptions:
ConfigurationException - All exceptions now use modern C# patterns (no Java-style exception chaining)
Events are wrapped as EventBean which provides:
EventType- Metadata about event structureGet(string propertyName)- Generic property access- Property getters are code-generated for performance
// Compile EPL
var compiler = EPCompilerProvider.Compiler;
var compiled = compiler.Compile("select * from MyEvent", args);
// Deploy to runtime
var runtime = EPRuntimeProvider.GetDefaultRuntime(config);
var deployment = runtime.DeploymentService.Deploy(compiled);
// Attach listener
var statement = deployment.Statements[0];
statement.AddListener(new MyUpdateListener());
// Send events
runtime.EventService.SendEventBean(eventBean, "MyEvent");- NEsperAll.sln - Complete solution with all projects
- NEsper.sln - Core projects only
- NEsper.Documentation.sln - Documentation projects
Plans are stored in .planning/ — see .planning/README.md for the index.
| Branch | Plan | Status |
|---|---|---|
service-locator-refactor |
.planning/service-locator-removal/PLAN.md |
Planned |
- The codebase is a port from Java Esper, so you'll see Java idioms translated to C#
- Code generation is central to performance - understand the forge→codegen→runtime flow
- The three-stage compilation model separates parsing, semantic analysis, and code generation
- Tests are comprehensive - regression suite has thousands of test cases
- Database tests require PostgreSQL running via Docker