From be14cae8b885593fc21d55d170124736acdbc6bc Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 10 Feb 2026 16:03:54 +0100 Subject: [PATCH 001/122] add pointer support to EDF --- CHANGELOG.md | 67 + README.md | 63 +- docs/basics/project-structure.md | 2 +- docs/networking/network-transparency.md | 11 +- net/edf/decode.go | 60 + net/edf/decode_ptr_test.go | 1877 +++++++++++++++++++++++ net/edf/edf.go | 3 + net/edf/edf_fuzzing_test.go | 228 +++ net/edf/encode.go | 74 +- net/edf/encode_ptr_test.go | 417 +++++ net/edf/pools.go | 1 + version.go | 2 +- 12 files changed, 2729 insertions(+), 76 deletions(-) create mode 100644 net/edf/decode_ptr_test.go create mode 100644 net/edf/edf_fuzzing_test.go create mode 100644 net/edf/encode_ptr_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c5ac9d2..8de25ce8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,73 @@ All notable changes to this project will be documented in this file. This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +#### [v3.3.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.330) 2026-xx-xx [tag version v1.999.330] #### + +* Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation + +#### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### + +* Introduced **mTLS support** - new `gen.CertAuthManager` interface for mutual TLS with CA pool management (`ClientCAs`, `RootCAs`, `ClientAuth`, `ServerName`). See [Mutual TLS](https://docs.ergo.services/networking/mutual-tls) documentation +* Introduced **NAT support** - new `RouteHost` and `RoutePort` options in `gen.AcceptorOptions` for nodes behind NAT or load balancers. See [Behind the NAT](https://docs.ergo.services/networking/behind-the-nat) documentation +* Introduced **spawn time control** - `InitTimeout` option in `gen.ProcessOptions` limits `ProcessInit` duration for both local and remote spawn. Remote spawn and application processes limited to max 15 seconds. See [Process](https://docs.ergo.services/basics/process) documentation +* Introduced **zip-bomb protection** - decompression size limits to prevent memory exhaustion attacks +* Added `gen.Ref` methods for request timeout tracking. See [Generic Types](https://docs.ergo.services/basics/generic-types#gen.ref): + - `Deadline` - returns deadline timestamp stored in reference + - `IsAlive` - checks if reference is still valid (deadline not exceeded) +* Added `gen.Node` methods. See [Node](https://docs.ergo.services/basics/node) documentation: + - `ProcessPID` / `ProcessName` - resolve process PID by name and vice versa + - `Call`, `CallWithTimeout`, `CallWithPriority`, `CallImportant`, `CallPID`, `CallProcessID`, `CallAlias` - synchronous requests from Node interface + - `Inspect` / `InspectMeta` - inspect processes and meta processes + - `MakeRefWithDeadline` - create reference with embedded deadline +* Added `gen.RemoteNode.ApplicationInfo` - query application information from remote nodes. See [Remote Start Application](https://docs.ergo.services/networking/remote-start-application) documentation +* Added `gen.Process` methods. See [Process](https://docs.ergo.services/basics/process) documentation: + - `SendWithPriorityAfter` - delayed send with priority + - `SendExitAfter` / `SendExitMetaAfter` - delayed exit signals + - `SendResponseImportant` / `SendResponseErrorImportant` - important delivery for responses +* Added `gen.Meta` methods. See [Meta Process](https://docs.ergo.services/basics/meta-process) documentation: + - `SendResponse` / `SendResponseError` - respond to requests from meta process + - `SendPriority` / `SetSendPriority` - message priority control + - `Compression` / `SetCompression` - compression settings + - `EnvDefault` - get environment variable with default value +* Added `gen.ApplicationSpec` / `gen.ApplicationInfo` fields: + - `Tags` - labels for instance selection (blue/green, canary, maintenance). See [Tags for Instance Selection](https://docs.ergo.services/basics/application#tags-for-instance-selection) + - `Map` - logical role to process name mapping. See [Process Role Mapping](https://docs.ergo.services/basics/application#process-role-mapping) +* Added **HandleInspect** implementations for all supervisor types (OFO, ARFO, SOFO) +* Fixed **LinkChild** in `RemoteNode.Spawn` / `RemoteNode.SpawnRegister` +* Fixed **args persistence** for Simple One For One supervisor - child processes now restart with their original spawn arguments +* Fixed **critical bug**: terminate signals (Link/Monitor exits) were incorrectly rejected due to wrong incarnation validation in network layer. Thanks to [@qjpcpu](https://github.com/qjpcpu) for reporting [#248](https://github.com/ergo-services/ergo/issues/248) +* Completely reworked internal **Target Manager** (`node/tm/`) - improved architecture for process, event, and node target management with comprehensive test coverage +* Completely reworked internal **Pub/Sub** mechanism - improved reliability and performance +* Improved **ProcessInit state** - more `gen.Process` methods now available during initialization: + - `Link*`, `Unlink*`, `Monitor*`, `Demonitor*` + - `Call*`, `Inspect`, `InspectMeta` + - `RegisterName`, `UnregisterName`, `RegisterEvent`, `UnregisterEvent` + - `SendResponse*`, `SendResponseError*` + - `CreateAlias`, `DeleteAlias` +* Introduced **shutdown timeout** - `ShutdownTimeout` option in `gen.NodeOptions` (default 3 minutes). During graceful shutdown, pending processes are logged every 5 seconds with state and queue info. After timeout, node force exits with error code 1. See [Node](https://docs.ergo.services/basics/node) documentation +* Added **pprof labels** for actor and meta process goroutines (with `--tags pprof`) - each process goroutine is labeled with its PID, each meta process with its Alias, making it easy to identify stuck processes in pprof output +* Improved API documentation - comprehensive godoc comments for all public interfaces +* **Documentation rewritten** - complete documentation now included in the repository (`docs/`) and available at [docs.ergo.services](https://docs.ergo.services) +* New documentation articles: + - [Project Structure](https://docs.ergo.services/basics/project-structure) - organizing projects with message isolation levels, deployment patterns, and evolution strategies + - [Building a Cluster](https://docs.ergo.services/advanced/building-a-cluster) - step-by-step guide to distributed systems with service discovery, load balancing, and failover + - [Message Versioning](https://docs.ergo.services/advanced/message-versioning) - evolving message contracts in distributed clusters with explicit versioning strategies + - [Handle Sync](https://docs.ergo.services/advanced/handle-sync) - synchronous message handling patterns + - [Important Delivery](https://docs.ergo.services/advanced/important-delivery) - guaranteed delivery mechanism + - [Pub/Sub Internals](https://docs.ergo.services/advanced/pub-sub-internals) - event system architecture + - [Debugging](https://docs.ergo.services/advanced/debugging) - build tags, pprof integration, troubleshooting stuck processes + +* **Extra Library - Actors** (https://github.com/ergo-services/actor): + - Introduced **Leader** actor - distributed leader election with Raft-inspired consensus algorithm. Features: term-based disambiguation, automatic failover, split-brain prevention through majority quorum, dynamic peer discovery. See [documentation](https://docs.ergo.services/extra-library/actors/leader) + - Introduced **Metrics** actor - Prometheus metrics exporter that collects node/network telemetry via HTTP endpoint. Features: automatic collection of node metrics (uptime, processes, memory), network metrics per remote node, extensible for custom metrics. See [documentation](https://docs.ergo.services/extra-library/actors/metrics) + +* **Extra Library - Meta Processes** (https://github.com/ergo-services/meta): + - Introduced **SSE** (Server-Sent Events) meta-process - unidirectional server-to-client streaming over HTTP. Features: server handler for accepting connections, client connection for external SSE endpoints, full SSE spec support (event types, IDs, retry hints, multi-line data), process pool with round-robin load balancing, Last-Event-ID for reconnection. See [documentation](https://docs.ergo.services/extra-library/meta-processes/sse) + +* **Benchmarks** (https://github.com/ergo-services/benchmarks): + - Introduced **Distributed Pub/Sub** benchmark - demonstrates event delivery to 1,000,000 subscribers across 10 nodes. Achieves 2.9M msg/sec delivery rate with only 10 network messages (one per consumer node) instead of 1M + + #### [v3.1.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.310) 2025-09-04 [tag version v1.999.310] #### **New Features** diff --git a/README.md b/README.md index 4a9d938b5..50d54b234 100644 --- a/README.md +++ b/README.md @@ -134,68 +134,9 @@ Starting from version 3.0.0, support for the Erlang network stack has been moved Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. -#### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### - -* Introduced **mTLS support** - new `gen.CertAuthManager` interface for mutual TLS with CA pool management (`ClientCAs`, `RootCAs`, `ClientAuth`, `ServerName`). See [Mutual TLS](https://docs.ergo.services/networking/mutual-tls) documentation -* Introduced **NAT support** - new `RouteHost` and `RoutePort` options in `gen.AcceptorOptions` for nodes behind NAT or load balancers. See [Behind the NAT](https://docs.ergo.services/networking/behind-the-nat) documentation -* Introduced **spawn time control** - `InitTimeout` option in `gen.ProcessOptions` limits `ProcessInit` duration for both local and remote spawn. Remote spawn and application processes limited to max 15 seconds. See [Process](https://docs.ergo.services/basics/process) documentation -* Introduced **zip-bomb protection** - decompression size limits to prevent memory exhaustion attacks -* Added `gen.Ref` methods for request timeout tracking. See [Generic Types](https://docs.ergo.services/basics/generic-types#gen.ref): - - `Deadline` - returns deadline timestamp stored in reference - - `IsAlive` - checks if reference is still valid (deadline not exceeded) -* Added `gen.Node` methods. See [Node](https://docs.ergo.services/basics/node) documentation: - - `ProcessPID` / `ProcessName` - resolve process PID by name and vice versa - - `Call`, `CallWithTimeout`, `CallWithPriority`, `CallImportant`, `CallPID`, `CallProcessID`, `CallAlias` - synchronous requests from Node interface - - `Inspect` / `InspectMeta` - inspect processes and meta processes - - `MakeRefWithDeadline` - create reference with embedded deadline -* Added `gen.RemoteNode.ApplicationInfo` - query application information from remote nodes. See [Remote Start Application](https://docs.ergo.services/networking/remote-start-application) documentation -* Added `gen.Process` methods. See [Process](https://docs.ergo.services/basics/process) documentation: - - `SendWithPriorityAfter` - delayed send with priority - - `SendExitAfter` / `SendExitMetaAfter` - delayed exit signals - - `SendResponseImportant` / `SendResponseErrorImportant` - important delivery for responses -* Added `gen.Meta` methods. See [Meta Process](https://docs.ergo.services/basics/meta-process) documentation: - - `SendResponse` / `SendResponseError` - respond to requests from meta process - - `SendPriority` / `SetSendPriority` - message priority control - - `Compression` / `SetCompression` - compression settings - - `EnvDefault` - get environment variable with default value -* Added `gen.ApplicationSpec` / `gen.ApplicationInfo` fields: - - `Tags` - labels for instance selection (blue/green, canary, maintenance). See [Tags for Instance Selection](https://docs.ergo.services/basics/application#tags-for-instance-selection) - - `Map` - logical role to process name mapping. See [Process Role Mapping](https://docs.ergo.services/basics/application#process-role-mapping) -* Added **HandleInspect** implementations for all supervisor types (OFO, ARFO, SOFO) -* Fixed **LinkChild** in `RemoteNode.Spawn` / `RemoteNode.SpawnRegister` -* Fixed **args persistence** for Simple One For One supervisor - child processes now restart with their original spawn arguments -* Fixed **critical bug**: terminate signals (Link/Monitor exits) were incorrectly rejected due to wrong incarnation validation in network layer. Thanks to [@qjpcpu](https://github.com/qjpcpu) for reporting [#248](https://github.com/ergo-services/ergo/issues/248) -* Completely reworked internal **Target Manager** (`node/tm/`) - improved architecture for process, event, and node target management with comprehensive test coverage -* Completely reworked internal **Pub/Sub** mechanism - improved reliability and performance -* Improved **ProcessInit state** - more `gen.Process` methods now available during initialization: - - `Link*`, `Unlink*`, `Monitor*`, `Demonitor*` - - `Call*`, `Inspect`, `InspectMeta` - - `RegisterName`, `UnregisterName`, `RegisterEvent`, `UnregisterEvent` - - `SendResponse*`, `SendResponseError*` - - `CreateAlias`, `DeleteAlias` -* Introduced **shutdown timeout** - `ShutdownTimeout` option in `gen.NodeOptions` (default 3 minutes). During graceful shutdown, pending processes are logged every 5 seconds with state and queue info. After timeout, node force exits with error code 1. See [Node](https://docs.ergo.services/basics/node) documentation -* Added **pprof labels** for actor and meta process goroutines (with `--tags pprof`) - each process goroutine is labeled with its PID, each meta process with its Alias, making it easy to identify stuck processes in pprof output -* Improved API documentation - comprehensive godoc comments for all public interfaces -* **Documentation rewritten** - complete documentation now included in the repository (`docs/`) and available at [docs.ergo.services](https://docs.ergo.services) -* New documentation articles: - - [Project Structure](https://docs.ergo.services/basics/project-structure) - organizing projects with message isolation levels, deployment patterns, and evolution strategies - - [Building a Cluster](https://docs.ergo.services/advanced/building-a-cluster) - step-by-step guide to distributed systems with service discovery, load balancing, and failover - - [Message Versioning](https://docs.ergo.services/advanced/message-versioning) - evolving message contracts in distributed clusters with explicit versioning strategies - - [Handle Sync](https://docs.ergo.services/advanced/handle-sync) - synchronous message handling patterns - - [Important Delivery](https://docs.ergo.services/advanced/important-delivery) - guaranteed delivery mechanism - - [Pub/Sub Internals](https://docs.ergo.services/advanced/pub-sub-internals) - event system architecture - - [Debugging](https://docs.ergo.services/advanced/debugging) - build tags, pprof integration, troubleshooting stuck processes - -* **Extra Library - Actors** (https://github.com/ergo-services/actor): - - Introduced **Leader** actor - distributed leader election with Raft-inspired consensus algorithm. Features: term-based disambiguation, automatic failover, split-brain prevention through majority quorum, dynamic peer discovery. See [documentation](https://docs.ergo.services/extra-library/actors/leader) - - Introduced **Metrics** actor - Prometheus metrics exporter that collects node/network telemetry via HTTP endpoint. Features: automatic collection of node metrics (uptime, processes, memory), network metrics per remote node, extensible for custom metrics. See [documentation](https://docs.ergo.services/extra-library/actors/metrics) - -* **Extra Library - Meta Processes** (https://github.com/ergo-services/meta): - - Introduced **SSE** (Server-Sent Events) meta-process - unidirectional server-to-client streaming over HTTP. Features: server handler for accepting connections, client connection for external SSE endpoints, full SSE spec support (event types, IDs, retry hints, multi-line data), process pool with round-robin load balancing, Last-Event-ID for reconnection. See [documentation](https://docs.ergo.services/extra-library/meta-processes/sse) - -* **Benchmarks** (https://github.com/ergo-services/benchmarks): - - Introduced **Distributed Pub/Sub** benchmark - demonstrates event delivery to 1,000,000 subscribers across 10 nodes. Achieves 2.9M msg/sec delivery rate with only 10 network messages (one per consumer node) instead of 1M +#### [v3.3.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.330) 2026-xx-xx [tag version v1.999.330] #### +* Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation ### Development and debugging ### diff --git a/docs/basics/project-structure.md b/docs/basics/project-structure.md index 310a9d3c1..82566358d 100644 --- a/docs/basics/project-structure.md +++ b/docs/basics/project-structure.md @@ -1134,7 +1134,7 @@ apps/ - Default to Level 4 for everything - Mix isolation levels arbitrarily - Use `any` or `interface{}` for messages -- Include pointers in network messages +- Include pointers to external resources (connections, files) in network messages ### Dependencies diff --git a/docs/networking/network-transparency.md b/docs/networking/network-transparency.md index bdcd61faa..0e2318310 100644 --- a/docs/networking/network-transparency.md +++ b/docs/networking/network-transparency.md @@ -227,16 +227,19 @@ type Order struct { } ``` -**No pointer types** - EDF rejects pointer types and structs containing pointer fields. This is by design: pointers are a local memory optimization and shouldn't be part of network contracts. A `*Database` field is meaningless to a remote actor - it can't dereference your memory address. Pointers express local sharing semantics that don't translate across address spaces. +**Pointer types** - Starting from version 3.3, EDF supports pointer types. Pointers can be `nil` or point to a value, and this state is preserved during encoding/decoding. Nested pointers (`**int`) are not supported. ```go +var discount *float64 // nil or value +var prices []*int // slice with nil elements +var cache map[string]*Config // map with nil values + type Order struct { - ID int64 - Cache *OrderCache // Registration fails - pointer is local optimization + Priority *int // optional field } ``` -For distributed references, use framework types designed for remote access: `gen.PID` (process reference), `gen.Alias` (named reference), `gen.Ref` (call reference). These work across nodes and provide location-independent semantics. +Note that pointers to external resources like `*Database` or `*Connection` are meaningless to a remote actor - it cannot dereference your memory address. Use pointers for optional value semantics, not for sharing local resources. For distributed references, use framework types: `gen.PID`, `gen.Alias`, `gen.Ref`. **Nested types must be registered first** - If your type contains other custom types, register the inner types before the outer type: diff --git a/net/edf/decode.go b/net/edf/decode.go index cd9740edd..0a9cee9e8 100644 --- a/net/edf/decode.go +++ b/net/edf/decode.go @@ -397,6 +397,66 @@ func decodeType(fold []byte, state *stateDecode) (*decoder, []byte, error) { case edtReg: return getRegDecoder(fold[1:], state) + + case edtPtr: + // unfold element type + decElem, f, err := decodeType(fold[1:], state) + if err != nil { + return nil, nil, fmt.Errorf("unable to unfold type (pointer): %s", err) + } + + ptrType := reflect.PointerTo(decElem.Type) + + fdec := func(value *reflect.Value, packet []byte, state *stateDecode) (*reflect.Value, []byte, error) { + if len(packet) == 0 { + return nil, nil, errDecodeEOD + } + + if packet[0] == edtNil { + // nil pointer + packet = packet[1:] + return nil, packet, nil + } + + if packet[0] != edtPtr { + return nil, nil, fmt.Errorf("incorrect pointer type %d", packet[0]) + } + packet = packet[1:] + + // use child state with decodeType = false (default) + if state.child == nil { + state.child = getPooledStateDecode(state.options) + } + state = state.child + + // decode element value + elem := reflect.Indirect(reflect.New(decElem.Type)) + _, packet, err := decElem.Decode(&elem, packet, state) + if err != nil { + return nil, nil, err + } + + // create pointer and set value + ptr := reflect.New(decElem.Type) + ptr.Elem().Set(elem) + + if value == nil { + value = &ptr + } else { + value.Set(ptr) + } + return value, packet, nil + } + + dec := decoder{ + Type: ptrType, + Decode: fdec, + } + if state.options.Cache != nil { + state.options.Cache.LoadOrStore(string(fold), &dec) + } + + return &dec, f, nil } if v, found := decoders.Load(fold[0]); found { diff --git a/net/edf/decode_ptr_test.go b/net/edf/decode_ptr_test.go new file mode 100644 index 000000000..69608d6c8 --- /dev/null +++ b/net/edf/decode_ptr_test.go @@ -0,0 +1,1877 @@ +package edf + +import ( + "fmt" + "reflect" + "testing" + "time" + + "ergo.services/ergo/gen" + "ergo.services/ergo/lib" +) + +// Basic pointer decode tests + +func TestDecodePtrInt(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int) + if ok == false { + t.Fatalf("expected *int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != 42 { + t.Fatalf("expected 42, got %d", *decodedPtr) + } +} + +func TestDecodePtrIntNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *int = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int) + if ok == false { + t.Fatalf("expected *int, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +func TestDecodePtrString(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + s := "hello" + ptr := &s + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*string) + if ok == false { + t.Fatalf("expected *string, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != "hello" { + t.Fatalf("expected 'hello', got '%s'", *decodedPtr) + } +} + +func TestDecodePtrStringNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *string = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*string) + if ok == false { + t.Fatalf("expected *string, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +func TestDecodePtrFloat64(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + f := 3.14 + ptr := &f + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*float64) + if ok == false { + t.Fatalf("expected *float64, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != 3.14 { + t.Fatalf("expected 3.14, got %f", *decodedPtr) + } +} + +func TestDecodePtrFloat64Nil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *float64 = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*float64) + if ok == false { + t.Fatalf("expected *float64, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +func TestDecodePtrBool(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := true + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*bool) + if ok == false { + t.Fatalf("expected *bool, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != true { + t.Fatalf("expected true, got %v", *decodedPtr) + } +} + +func TestDecodePtrBoolNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *bool = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*bool) + if ok == false { + t.Fatalf("expected *bool, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +// Slice of pointers decode tests + +func TestDecodeSlicePtr(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + a, b2, c := 1, 2, 3 + slice := []*int{&a, nil, &b2, nil, &c} + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedSlice, ok := decoded.([]*int) + if ok == false { + t.Fatalf("expected []*int, got %T", decoded) + } + if len(decodedSlice) != 5 { + t.Fatalf("expected len 5, got %d", len(decodedSlice)) + } + + // check values + if decodedSlice[0] == nil || *decodedSlice[0] != 1 { + t.Fatal("incorrect value at index 0") + } + if decodedSlice[1] != nil { + t.Fatal("expected nil at index 1") + } + if decodedSlice[2] == nil || *decodedSlice[2] != 2 { + t.Fatal("incorrect value at index 2") + } + if decodedSlice[3] != nil { + t.Fatal("expected nil at index 3") + } + if decodedSlice[4] == nil || *decodedSlice[4] != 3 { + t.Fatal("incorrect value at index 4") + } +} + +func TestDecodeSlicePtrEmpty(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + slice := []*int{} + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedSlice, ok := decoded.([]*int) + if ok == false { + t.Fatalf("expected []*int, got %T", decoded) + } + if len(decodedSlice) != 0 { + t.Fatalf("expected len 0, got %d", len(decodedSlice)) + } +} + +func TestDecodeSlicePtrNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var slice []*int = nil + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + // nil slice decodes to nil interface, not typed nil + if decoded != nil { + // if it decoded to a typed value, check it + decodedSlice, ok := decoded.([]*int) + if ok == false { + t.Fatalf("expected []*int or nil, got %T", decoded) + } + if decodedSlice != nil { + t.Fatal("expected nil slice") + } + } +} + +// Pointer to slice + +func TestDecodePtrSlice(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + slice := []int{1, 2, 3} + ptr := &slice + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]int) + if ok == false { + t.Fatalf("expected *[]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if reflect.DeepEqual(*decodedPtr, []int{1, 2, 3}) == false { + t.Fatalf("expected [1,2,3], got %v", *decodedPtr) + } +} + +func TestDecodePtrSliceNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *[]int = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]int) + if ok == false { + t.Fatalf("expected *[]int, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +// Pointer to map + +func TestDecodePtrMap(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + m := map[string]int{"a": 1, "b": 2} + ptr := &m + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*map[string]int) + if ok == false { + t.Fatalf("expected *map[string]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if (*decodedPtr)["a"] != 1 || (*decodedPtr)["b"] != 2 { + t.Fatalf("incorrect map values: %v", *decodedPtr) + } +} + +func TestDecodePtrMapNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *map[string]int = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*map[string]int) + if ok == false { + t.Fatalf("expected *map[string]int, got %T", decoded) + } + if decodedPtr != nil { + t.Fatalf("expected nil, got %v", decodedPtr) + } +} + +// Map with pointer values + +func TestDecodeMapPtrValue(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v1, v2 := 10, 20 + m := map[string]*int{"a": &v1, "b": nil, "c": &v2} + + if err := Encode(m, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dm, ok := decoded.(map[string]*int) + if ok == false { + t.Fatalf("expected map[string]*int, got %T", decoded) + } + + if dm["a"] == nil || *dm["a"] != 10 { + t.Fatal("incorrect value for key 'a'") + } + if dm["b"] != nil { + t.Fatal("expected nil for key 'b'") + } + if dm["c"] == nil || *dm["c"] != 20 { + t.Fatal("incorrect value for key 'c'") + } +} + +// Pointer in any field (struct) + +type testPtrStructWithAny struct { + Value any +} + +func init() { + RegisterTypeOf(testPtrStructWithAny{}) +} + +func TestDecodePtrInAny(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 123 + s := testPtrStructWithAny{Value: &v} + + if err := Encode(s, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + ds, ok := decoded.(testPtrStructWithAny) + if ok == false { + t.Fatalf("expected testPtrStructWithAny, got %T", decoded) + } + + ptr, ok := ds.Value.(*int) + if ok == false { + t.Fatalf("expected *int in any, got %T", ds.Value) + } + if ptr == nil || *ptr != 123 { + t.Fatalf("expected 123, got %v", ptr) + } +} + +func TestDecodePtrInAnyNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + s := testPtrStructWithAny{Value: (*int)(nil)} + + if err := Encode(s, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + ds, ok := decoded.(testPtrStructWithAny) + if ok == false { + t.Fatalf("expected testPtrStructWithAny, got %T", decoded) + } + + // nil pointer in any becomes typed nil (*int)(nil) + ptr, ok := ds.Value.(*int) + if ok == false { + // might also be untyped nil + if ds.Value != nil { + t.Fatalf("expected *int or nil in any, got %T", ds.Value) + } + } else if ptr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodeSlicePtrInAny(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + a, c := 1, 3 + slice := []*int{&a, nil, &c} + s := testPtrStructWithAny{Value: slice} + + if err := Encode(s, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + ds, ok := decoded.(testPtrStructWithAny) + if ok == false { + t.Fatalf("expected testPtrStructWithAny, got %T", decoded) + } + + decodedSlice, ok := ds.Value.([]*int) + if ok == false { + t.Fatalf("expected []*int in any, got %T", ds.Value) + } + + if len(decodedSlice) != 3 { + t.Fatalf("expected len 3, got %d", len(decodedSlice)) + } + if decodedSlice[0] == nil || *decodedSlice[0] != 1 { + t.Fatal("incorrect value at index 0") + } + if decodedSlice[1] != nil { + t.Fatal("expected nil at index 1") + } + if decodedSlice[2] == nil || *decodedSlice[2] != 3 { + t.Fatal("incorrect value at index 2") + } +} + +// Pointer to nil slice (not nil pointer, pointer to nil slice value) + +func TestDecodePtrToNilSlice(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var slice []int = nil + ptr := &slice // pointer to nil slice + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]int) + if ok == false { + t.Fatalf("expected *[]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != nil { + t.Fatalf("expected nil slice, got %v", *decodedPtr) + } +} + +// Pointer to nil map + +func TestDecodePtrToNilMap(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var m map[string]int = nil + ptr := &m // pointer to nil map + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*map[string]int) + if ok == false { + t.Fatalf("expected *map[string]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != nil { + t.Fatalf("expected nil map, got %v", *decodedPtr) + } +} + +// Pointer to empty slice + +func TestDecodePtrToEmptySlice(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + slice := []int{} + ptr := &slice + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]int) + if ok == false { + t.Fatalf("expected *[]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr == nil { + t.Fatal("expected non-nil slice") + } + if len(*decodedPtr) != 0 { + t.Fatalf("expected empty slice, got len %d", len(*decodedPtr)) + } +} + +// Corner case: pointer to pointer to slice element (nested through slice) + +func TestDecodeSlicePtrString(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + s1, s2 := "hello", "world" + slice := []*string{&s1, nil, &s2} + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedSlice, ok := decoded.([]*string) + if ok == false { + t.Fatalf("expected []*string, got %T", decoded) + } + + if len(decodedSlice) != 3 { + t.Fatalf("expected len 3, got %d", len(decodedSlice)) + } + if decodedSlice[0] == nil || *decodedSlice[0] != "hello" { + t.Fatal("incorrect value at index 0") + } + if decodedSlice[1] != nil { + t.Fatal("expected nil at index 1") + } + if decodedSlice[2] == nil || *decodedSlice[2] != "world" { + t.Fatal("incorrect value at index 2") + } +} + +// Test malformed data + +func TestDecodePtrMalformedMissingValue(t *testing.T) { + // type descriptor for *int but no value bytes + packet := []byte{ + edtType, 0, 2, + edtPtr, edtInt, + // missing edtPtr or edtNil marker + } + + _, _, err := Decode(packet, Options{}) + if err == nil { + t.Fatal("expected error for malformed data") + } +} + +func TestDecodePtrMalformedInvalidMarker(t *testing.T) { + // type descriptor for *int with invalid marker + packet := []byte{ + edtType, 0, 2, + edtPtr, edtInt, + edtString, // wrong marker + } + + _, _, err := Decode(packet, Options{}) + if err == nil { + t.Fatal("expected error for invalid marker") + } +} + +// Large value through pointer + +func TestDecodePtrLargeInt(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := int64(9223372036854775807) // max int64 + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int64) + if ok == false { + t.Fatalf("expected *int64, got %T", decoded) + } + if *decodedPtr != 9223372036854775807 { + t.Fatalf("expected max int64, got %d", *decodedPtr) + } +} + +// Slice of slices containing pointers + +func TestDecodeNestedSlicePtr(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + a, b2 := 1, 2 + c, d := 3, 4 + nested := [][]*int{ + {&a, nil, &b2}, + {&c, &d}, + } + + if err := Encode(nested, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dn, ok := decoded.([][]*int) + if ok == false { + t.Fatalf("expected [][]*int, got %T", decoded) + } + + if len(dn) != 2 { + t.Fatalf("expected 2 outer slices, got %d", len(dn)) + } + + // first inner slice + if len(dn[0]) != 3 { + t.Fatalf("expected 3 elements in first slice, got %d", len(dn[0])) + } + if *dn[0][0] != 1 || dn[0][1] != nil || *dn[0][2] != 2 { + fmt.Printf("got: %v %v %v\n", dn[0][0], dn[0][1], dn[0][2]) + t.Fatal("incorrect values in first slice") + } + + // second inner slice + if len(dn[1]) != 2 { + t.Fatalf("expected 2 elements in second slice, got %d", len(dn[1])) + } + if *dn[1][0] != 3 || *dn[1][1] != 4 { + t.Fatal("incorrect values in second slice") + } +} + +// Pointer to binary ([]byte) + +func TestDecodePtrBinary(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + bin := []byte{1, 2, 3, 4, 5} + ptr := &bin + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]byte) + if ok == false { + t.Fatalf("expected *[]byte, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if reflect.DeepEqual(*decodedPtr, []byte{1, 2, 3, 4, 5}) == false { + t.Fatalf("expected [1,2,3,4,5], got %v", *decodedPtr) + } +} + +func TestDecodePtrBinaryNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *[]byte = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[]byte) + if ok == false { + t.Fatalf("expected *[]byte, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Pointer to Ergo types + +func TestDecodePtrAtom(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + atom := gen.Atom("test_atom") + ptr := &atom + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Atom) + if ok == false { + t.Fatalf("expected *gen.Atom, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != "test_atom" { + t.Fatalf("expected 'test_atom', got '%s'", *decodedPtr) + } +} + +func TestDecodePtrAtomNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.Atom = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Atom) + if ok == false { + t.Fatalf("expected *gen.Atom, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodePtrTime(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + tm := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC) + ptr := &tm + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*time.Time) + if ok == false { + t.Fatalf("expected *time.Time, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Equal(tm) == false { + t.Fatalf("expected %v, got %v", tm, *decodedPtr) + } +} + +func TestDecodePtrTimeNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *time.Time = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*time.Time) + if ok == false { + t.Fatalf("expected *time.Time, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Array of pointers + +func TestDecodeArrayPtr(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + a, c := 1, 3 + arr := [3]*int{&a, nil, &c} + + if err := Encode(arr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedArr, ok := decoded.([3]*int) + if ok == false { + t.Fatalf("expected [3]*int, got %T", decoded) + } + + if decodedArr[0] == nil || *decodedArr[0] != 1 { + t.Fatal("incorrect value at index 0") + } + if decodedArr[1] != nil { + t.Fatal("expected nil at index 1") + } + if decodedArr[2] == nil || *decodedArr[2] != 3 { + t.Fatal("incorrect value at index 2") + } +} + +// Pointer to array + +func TestDecodePtrArray(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + arr := [3]int{1, 2, 3} + ptr := &arr + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[3]int) + if ok == false { + t.Fatalf("expected *[3]int, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != [3]int{1, 2, 3} { + t.Fatalf("expected [1,2,3], got %v", *decodedPtr) + } +} + +func TestDecodePtrArrayNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *[3]int = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*[3]int) + if ok == false { + t.Fatalf("expected *[3]int, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Registered struct with pointer fields + +type testStructWithPtrField struct { + Name string + Value *int + Data *string +} + +func init() { + RegisterTypeOf(testStructWithPtrField{}) +} + +func TestDecodeStructWithPtrField(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + s := "hello" + st := testStructWithPtrField{ + Name: "test", + Value: &v, + Data: &s, + } + + if err := Encode(st, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dst, ok := decoded.(testStructWithPtrField) + if ok == false { + t.Fatalf("expected testStructWithPtrField, got %T", decoded) + } + + if dst.Name != "test" { + t.Fatalf("expected Name='test', got '%s'", dst.Name) + } + if dst.Value == nil || *dst.Value != 42 { + t.Fatal("incorrect Value field") + } + if dst.Data == nil || *dst.Data != "hello" { + t.Fatal("incorrect Data field") + } +} + +func TestDecodeStructWithPtrFieldNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + st := testStructWithPtrField{ + Name: "test", + Value: nil, + Data: nil, + } + + if err := Encode(st, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dst, ok := decoded.(testStructWithPtrField) + if ok == false { + t.Fatalf("expected testStructWithPtrField, got %T", decoded) + } + + if dst.Name != "test" { + t.Fatalf("expected Name='test', got '%s'", dst.Name) + } + if dst.Value != nil { + t.Fatal("expected nil Value field") + } + if dst.Data != nil { + t.Fatal("expected nil Data field") + } +} + +func TestDecodeStructWithPtrFieldMixed(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 99 + st := testStructWithPtrField{ + Name: "mixed", + Value: &v, + Data: nil, // one nil, one non-nil + } + + if err := Encode(st, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dst, ok := decoded.(testStructWithPtrField) + if ok == false { + t.Fatalf("expected testStructWithPtrField, got %T", decoded) + } + + if dst.Name != "mixed" { + t.Fatalf("expected Name='mixed', got '%s'", dst.Name) + } + if dst.Value == nil || *dst.Value != 99 { + t.Fatal("incorrect Value field") + } + if dst.Data != nil { + t.Fatal("expected nil Data field") + } +} + +// Additional integer pointer types + +func TestDecodePtrInt8(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := int8(127) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int8) + if ok == false { + t.Fatalf("expected *int8, got %T", decoded) + } + if *decodedPtr != 127 { + t.Fatalf("expected 127, got %d", *decodedPtr) + } +} + +func TestDecodePtrInt16(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := int16(32767) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int16) + if ok == false { + t.Fatalf("expected *int16, got %T", decoded) + } + if *decodedPtr != 32767 { + t.Fatalf("expected 32767, got %d", *decodedPtr) + } +} + +func TestDecodePtrInt32(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := int32(2147483647) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*int32) + if ok == false { + t.Fatalf("expected *int32, got %T", decoded) + } + if *decodedPtr != 2147483647 { + t.Fatalf("expected 2147483647, got %d", *decodedPtr) + } +} + +func TestDecodePtrUint(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := uint(18446744073709551615) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*uint) + if ok == false { + t.Fatalf("expected *uint, got %T", decoded) + } + if *decodedPtr != 18446744073709551615 { + t.Fatalf("expected max uint, got %d", *decodedPtr) + } +} + +func TestDecodePtrUint8(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := uint8(255) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*uint8) + if ok == false { + t.Fatalf("expected *uint8, got %T", decoded) + } + if *decodedPtr != 255 { + t.Fatalf("expected 255, got %d", *decodedPtr) + } +} + +func TestDecodePtrUint16(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := uint16(65535) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*uint16) + if ok == false { + t.Fatalf("expected *uint16, got %T", decoded) + } + if *decodedPtr != 65535 { + t.Fatalf("expected 65535, got %d", *decodedPtr) + } +} + +func TestDecodePtrUint32(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := uint32(4294967295) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*uint32) + if ok == false { + t.Fatalf("expected *uint32, got %T", decoded) + } + if *decodedPtr != 4294967295 { + t.Fatalf("expected 4294967295, got %d", *decodedPtr) + } +} + +func TestDecodePtrUint64(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := uint64(18446744073709551615) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*uint64) + if ok == false { + t.Fatalf("expected *uint64, got %T", decoded) + } + if *decodedPtr != 18446744073709551615 { + t.Fatalf("expected max uint64, got %d", *decodedPtr) + } +} + +func TestDecodePtrFloat32(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := float32(3.14) + ptr := &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*float32) + if ok == false { + t.Fatalf("expected *float32, got %T", decoded) + } + if *decodedPtr != float32(3.14) { + t.Fatalf("expected 3.14, got %f", *decodedPtr) + } +} + +// Ergo types pointers + +func TestDecodePtrPID(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + pid := gen.PID{Node: "test@localhost", ID: 12345, Creation: 1} + ptr := &pid + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.PID) + if ok == false { + t.Fatalf("expected *gen.PID, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Node != "test@localhost" || decodedPtr.ID != 12345 { + t.Fatalf("incorrect PID: %v", *decodedPtr) + } +} + +func TestDecodePtrPIDNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.PID = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.PID) + if ok == false { + t.Fatalf("expected *gen.PID, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodePtrProcessID(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + pid := gen.ProcessID{Node: "test@localhost", Name: "myprocess"} + ptr := &pid + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.ProcessID) + if ok == false { + t.Fatalf("expected *gen.ProcessID, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Node != "test@localhost" || decodedPtr.Name != "myprocess" { + t.Fatalf("incorrect ProcessID: %v", *decodedPtr) + } +} + +func TestDecodePtrProcessIDNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.ProcessID = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.ProcessID) + if ok == false { + t.Fatalf("expected *gen.ProcessID, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodePtrRef(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + ref := gen.Ref{Node: "test@localhost", Creation: 1, ID: [3]uint64{1, 2, 3}} + ptr := &ref + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Ref) + if ok == false { + t.Fatalf("expected *gen.Ref, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Node != "test@localhost" || decodedPtr.ID != [3]uint64{1, 2, 3} { + t.Fatalf("incorrect Ref: %v", *decodedPtr) + } +} + +func TestDecodePtrRefNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.Ref = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Ref) + if ok == false { + t.Fatalf("expected *gen.Ref, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodePtrAlias(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + alias := gen.Alias{Node: "test@localhost", Creation: 1, ID: [3]uint64{4, 5, 6}} + ptr := &alias + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Alias) + if ok == false { + t.Fatalf("expected *gen.Alias, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Node != "test@localhost" || decodedPtr.ID != [3]uint64{4, 5, 6} { + t.Fatalf("incorrect Alias: %v", *decodedPtr) + } +} + +func TestDecodePtrAliasNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.Alias = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Alias) + if ok == false { + t.Fatalf("expected *gen.Alias, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +func TestDecodePtrEvent(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + event := gen.Event{Node: "test@localhost", Name: "myevent"} + ptr := &event + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Event) + if ok == false { + t.Fatalf("expected *gen.Event, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.Node != "test@localhost" || decodedPtr.Name != "myevent" { + t.Fatalf("incorrect Event: %v", *decodedPtr) + } +} + +func TestDecodePtrEventNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *gen.Event = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*gen.Event) + if ok == false { + t.Fatalf("expected *gen.Event, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Pointer to registered struct + +type testRegisteredStruct struct { + X int + Y string +} + +func init() { + RegisterTypeOf(testRegisteredStruct{}) +} + +func TestDecodePtrToRegisteredStruct(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + st := testRegisteredStruct{X: 42, Y: "hello"} + ptr := &st + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*testRegisteredStruct) + if ok == false { + t.Fatalf("expected *testRegisteredStruct, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if decodedPtr.X != 42 || decodedPtr.Y != "hello" { + t.Fatalf("incorrect struct: %v", *decodedPtr) + } +} + +func TestDecodePtrToRegisteredStructNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *testRegisteredStruct = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*testRegisteredStruct) + if ok == false { + t.Fatalf("expected *testRegisteredStruct, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Slice of pointers to registered struct + +func TestDecodeSlicePtrToRegisteredStruct(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + st1 := testRegisteredStruct{X: 1, Y: "one"} + st2 := testRegisteredStruct{X: 2, Y: "two"} + slice := []*testRegisteredStruct{&st1, nil, &st2} + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedSlice, ok := decoded.([]*testRegisteredStruct) + if ok == false { + t.Fatalf("expected []*testRegisteredStruct, got %T", decoded) + } + if len(decodedSlice) != 3 { + t.Fatalf("expected len 3, got %d", len(decodedSlice)) + } + if decodedSlice[0] == nil || decodedSlice[0].X != 1 { + t.Fatal("incorrect value at index 0") + } + if decodedSlice[1] != nil { + t.Fatal("expected nil at index 1") + } + if decodedSlice[2] == nil || decodedSlice[2].X != 2 { + t.Fatal("incorrect value at index 2") + } +} + +// Type alias for pointer: type myPtrType *bool + +type myPtrBool *bool + +func TestDecodeTypePtrAlias(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := true + var ptr myPtrBool = &v + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + // Note: decoded type will be *bool, not myPtrBool + // because EDF doesn't preserve type aliases + decodedPtr, ok := decoded.(*bool) + if ok == false { + t.Fatalf("expected *bool, got %T", decoded) + } + if decodedPtr == nil { + t.Fatal("expected non-nil pointer") + } + if *decodedPtr != true { + t.Fatal("expected true") + } +} + +func TestDecodeTypePtrAliasNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr myPtrBool = nil + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + decodedPtr, ok := decoded.(*bool) + if ok == false { + t.Fatalf("expected *bool, got %T", decoded) + } + if decodedPtr != nil { + t.Fatal("expected nil pointer") + } +} + +// Pointer to type alias (*myPtrBool = **bool) - should be rejected + +func TestDecodePtrToTypePtrAlias(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := true + var ptr myPtrBool = &v + ptrptr := &ptr // this is *myPtrBool which is **bool + + err := Encode(ptrptr, b, Options{}) + if err == nil { + t.Fatal("expected error for pointer to pointer type alias") + } + // Should get "nested pointer type is not supported" error +} + +// Pointer as map key + +func TestDecodeMapWithPtrKey(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + k := "key" + m := map[*string]int{&k: 42} + + if err := Encode(m, b, Options{}); err != nil { + t.Fatal(err) + } + + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dm, ok := decoded.(map[*string]int) + if ok == false { + t.Fatalf("expected map[*string]int, got %T", decoded) + } + + if len(dm) != 1 { + t.Fatalf("expected 1 entry, got %d", len(dm)) + } + + for ptr, v := range dm { + if ptr == nil || *ptr != "key" { + t.Fatal("incorrect key") + } + if v != 42 { + t.Fatal("incorrect value") + } + } +} diff --git a/net/edf/edf.go b/net/edf/edf.go index 17441e6ae..c1f5757fc 100644 --- a/net/edf/edf.go +++ b/net/edf/edf.go @@ -12,6 +12,7 @@ type Options struct { RegCache *sync.Map // type/name => id (encoding), id => type (for decoding) ErrCache *sync.Map // error => id (for encoder), id => error (for decoder) Cache *sync.Map // common cache (caching reflect.Type => encoder, string([]byte) => decoder) + MaxDepth int // max encoding depth for pointers (default 100) } const ( @@ -40,6 +41,8 @@ const ( edtArray = byte(158) // 0x9e edtMap = byte(159) // 0x9f + edtPtr = byte(160) // 0xa0 + edtPID = byte(170) // 0xaa edtProcessID = byte(171) // 0xab edtAlias = byte(172) // 0xac diff --git a/net/edf/edf_fuzzing_test.go b/net/edf/edf_fuzzing_test.go new file mode 100644 index 000000000..3d701c7bc --- /dev/null +++ b/net/edf/edf_fuzzing_test.go @@ -0,0 +1,228 @@ +package edf + +import ( + "bytes" + "testing" + + "ergo.services/ergo/gen" + "ergo.services/ergo/lib" +) + +type fuzzInnerStruct struct { + Value int + Name string + Flag bool + FloatVal float64 +} + +type fuzzMiddleStruct struct { + Inner fuzzInnerStruct + InnerPtr *fuzzInnerStruct + Values []int + ValuesPtr []*int + Data map[string]int + DataPtr map[string]*int +} + +type fuzzComplexStruct struct { + Int8Val int8 + Int16Val int16 + Int32Val int32 + Int64Val int64 + Uint8Val uint8 + Uint16Val uint16 + Uint32Val uint32 + Uint64Val uint64 + Float32 float32 + Float64 float64 + Bool bool + String string + Binary []byte + + IntPtr *int + StringPtr *string + FloatPtr *float64 + BoolPtr *bool + + Atom gen.Atom + AtomPtr *gen.Atom + PID gen.PID + PIDPtr *gen.PID + ProcessID gen.ProcessID + Ref gen.Ref + Alias gen.Alias + Event gen.Event + + Middle fuzzMiddleStruct + MiddlePtr *fuzzMiddleStruct + + IntSlice []int + StringSlice []string + StructSlice []fuzzInnerStruct + StructPtrSlice []*fuzzInnerStruct + PtrSlice []*int + + StringIntMap map[string]int + IntStringMap map[int]string + StringStructMap map[string]fuzzInnerStruct + StringPtrMap map[string]*int +} + +func init() { + RegisterTypeOf(fuzzInnerStruct{}) + RegisterTypeOf(fuzzMiddleStruct{}) + RegisterTypeOf(fuzzComplexStruct{}) +} + +// compare by re-encoding decoded value and comparing bytes +func compareByEncode(original, decoded any) bool { + b1 := lib.TakeBuffer() + defer lib.ReleaseBuffer(b1) + b2 := lib.TakeBuffer() + defer lib.ReleaseBuffer(b2) + + if err := Encode(original, b1, Options{}); err != nil { + return false + } + if err := Encode(decoded, b2, Options{}); err != nil { + return false + } + return bytes.Equal(b1.B, b2.B) +} + +func FuzzComplexStruct(f *testing.F) { + // seed corpus - разные комбинации примитивов + f.Add( + int8(0), int16(0), int32(0), int64(0), + uint8(0), uint16(0), uint32(0), uint64(0), + float32(0), float64(0), false, "", []byte{}, + ) + f.Add( + int8(42), int16(1000), int32(100000), int64(1000000000), + uint8(255), uint16(65535), uint32(100000), uint64(1000000000), + float32(3.14), float64(3.14159), true, "hello", []byte{1, 2, 3}, + ) + f.Add( + int8(-128), int16(-32768), int32(-2147483648), int64(-9223372036854775808), + uint8(0), uint16(0), uint32(0), uint64(0), + float32(-1.5), float64(-1.5), false, "тест", []byte{0xff, 0xfe}, + ) + + f.Fuzz(func(t *testing.T, + i8 int8, i16 int16, i32 int32, i64 int64, + u8 uint8, u16 uint16, u32 uint32, u64 uint64, + f32 float32, f64 float64, b bool, s string, bin []byte, + ) { + // limit string for Atom (max 255 bytes) + if len(s) > 255 { + s = s[:255] + } + + // build pointers based on values + intVal := int(i64) + floatVal := f64 + boolVal := b + + innerVal := int(i32) + innerName := s + innerFloat := f64 + + original := fuzzComplexStruct{ + Int8Val: i8, + Int16Val: i16, + Int32Val: i32, + Int64Val: i64, + Uint8Val: u8, + Uint16Val: u16, + Uint32Val: u32, + Uint64Val: u64, + Float32: f32, + Float64: f64, + Bool: b, + String: s, + Binary: bin, + + IntPtr: &intVal, + StringPtr: &s, + FloatPtr: &floatVal, + BoolPtr: &boolVal, + + Atom: gen.Atom(s), + AtomPtr: nil, + PID: gen.PID{Node: gen.Atom(s), ID: u64, Creation: i64}, + PIDPtr: nil, + ProcessID: gen.ProcessID{Node: gen.Atom(s), Name: gen.Atom(s)}, + Ref: gen.Ref{Node: gen.Atom(s), Creation: i64, ID: [3]uint64{u64, u64, u64}}, + Alias: gen.Alias{Node: gen.Atom(s), Creation: i64, ID: [3]uint64{u64, u64, u64}}, + Event: gen.Event{Node: gen.Atom(s), Name: gen.Atom(s)}, + + Middle: fuzzMiddleStruct{ + Inner: fuzzInnerStruct{ + Value: innerVal, + Name: innerName, + Flag: b, + FloatVal: innerFloat, + }, + InnerPtr: &fuzzInnerStruct{Value: innerVal, Name: innerName, Flag: b, FloatVal: innerFloat}, + Values: []int{int(i64), int(i32), int(i16)}, + ValuesPtr: []*int{&intVal, nil, &innerVal}, + Data: map[string]int{s: int(i64)}, + DataPtr: map[string]*int{s: &intVal}, + }, + MiddlePtr: &fuzzMiddleStruct{ + Inner: fuzzInnerStruct{Value: innerVal, Name: innerName, Flag: b, FloatVal: innerFloat}, + InnerPtr: nil, + Values: []int{int(i64)}, + ValuesPtr: []*int{nil}, + Data: map[string]int{}, + DataPtr: map[string]*int{}, + }, + + IntSlice: []int{int(i64), int(i32), int(i16), int(i8)}, + StringSlice: []string{s, s}, + StructSlice: []fuzzInnerStruct{{Value: innerVal, Name: innerName, Flag: b, FloatVal: innerFloat}}, + StructPtrSlice: []*fuzzInnerStruct{nil, &fuzzInnerStruct{Value: innerVal, Name: innerName, Flag: b, FloatVal: innerFloat}}, + PtrSlice: []*int{&intVal, nil, &innerVal}, + + StringIntMap: map[string]int{s: int(i64)}, + IntStringMap: map[int]string{int(i64): s}, + StringStructMap: map[string]fuzzInnerStruct{s: {Value: innerVal, Name: innerName, Flag: b, FloatVal: innerFloat}}, + StringPtrMap: map[string]*int{s: &intVal}, + } + + buf := lib.TakeBuffer() + defer lib.ReleaseBuffer(buf) + + if err := Encode(original, buf, Options{}); err != nil { + t.Fatalf("encode error: %s", err) + } + + decoded, _, err := Decode(buf.B, Options{}) + if err != nil { + t.Fatalf("decode error: %s", err) + } + + decodedStruct, ok := decoded.(fuzzComplexStruct) + if ok == false { + t.Fatalf("expected fuzzComplexStruct, got %T", decoded) + } + + if compareByEncode(original, decodedStruct) == false { + t.Fatalf("mismatch after roundtrip") + } + }) +} + +// FuzzDecode - check decoder doesn't panic on random bytes +func FuzzDecode(f *testing.F) { + f.Add([]byte{edtNil}) + f.Add([]byte{edtBool, 1}) + f.Add([]byte{edtInt, 0, 0, 0, 0, 0, 0, 0, 42}) + f.Add([]byte{edtString, 0, 5, 'h', 'e', 'l', 'l', 'o'}) + f.Add([]byte{edtType, 0, 2, edtPtr, edtInt, edtNil}) + f.Add([]byte{edtType, 0, 2, edtPtr, edtInt, edtPtr, 0, 0, 0, 0, 0, 0, 0, 42}) + + f.Fuzz(func(t *testing.T, data []byte) { + Decode(data, Options{}) + }) +} diff --git a/net/edf/encode.go b/net/edf/encode.go index 8daf68d5a..334622783 100644 --- a/net/edf/encode.go +++ b/net/edf/encode.go @@ -11,19 +11,19 @@ import ( "ergo.services/ergo/lib" ) +const maxEncodeDepth = 100 + var ( - ErrBinaryTooLong = fmt.Errorf("binary too long - max allowed length is 2^32-1 bytes (4GB)") - ErrStringTooLong = fmt.Errorf("string too long - max allowed length is 2^16-1 (65535) bytes") - ErrAtomTooLong = fmt.Errorf("atom too long - max allowed length is 255 bytes") - ErrErrorTooLong = fmt.Errorf("error too long - max allowed length is 32767 bytes") + ErrBinaryTooLong = fmt.Errorf("binary too long - max allowed length is 2^32-1 bytes (4GB)") + ErrStringTooLong = fmt.Errorf("string too long - max allowed length is 2^16-1 (65535) bytes") + ErrAtomTooLong = fmt.Errorf("atom too long - max allowed length is 255 bytes") + ErrErrorTooLong = fmt.Errorf("error too long - max allowed length is 32767 bytes") + ErrMaxDepthExceeded = fmt.Errorf("max encoding depth exceeded (cyclic reference?)") ) type stateEncode struct { child *stateEncode - - // TODO loop detection (in slices) - //loop map[unsafe.Pointer]struct{} - //ptr unsafe.Pointer + depth int encodeType bool @@ -297,7 +297,63 @@ func getEncoder(t reflect.Type, state *stateEncode) (*encoder, error) { return enc, nil case reflect.Pointer: - return nil, fmt.Errorf("pointer type is not supported") + elemType := t.Elem() + // reject nested pointers + if elemType.Kind() == reflect.Pointer { + return nil, fmt.Errorf("nested pointer type is not supported") + } + + encElem, err := getEncoder(elemType, state) + if err != nil { + return nil, err + } + + elemPrefix := encElem.Prefix + if state.options.RegCache != nil { + if v, found := state.options.RegCache.Load(elemType); found { + elemPrefix = v.([]byte) + } + } + prefix := append([]byte{edtPtr}, elemPrefix...) + + fenc := func(value reflect.Value, b *lib.Buffer, state *stateEncode) error { + state.depth++ + maxDepth := state.options.MaxDepth + if maxDepth == 0 { + maxDepth = maxEncodeDepth + } + if state.depth > maxDepth { + return ErrMaxDepthExceeded + } + + if state.encodeType { + buf := b.Extend(3) + buf[0] = edtType + binary.BigEndian.PutUint16(buf[1:3], uint16(len(prefix))) + b.Append(prefix) + } + + if value.IsNil() { + state.depth-- + b.AppendByte(edtNil) + return nil + } + + b.AppendByte(edtPtr) + state.encodeType = false + err := encElem.Encode(value.Elem(), b, state) + state.depth-- + return err + } + + enc := &encoder{ + Prefix: prefix, + Encode: fenc, + } + if state.options.Cache != nil { + state.options.Cache.Store(t, enc) + } + return enc, nil } // look among the standard types diff --git a/net/edf/encode_ptr_test.go b/net/edf/encode_ptr_test.go new file mode 100644 index 000000000..a2ffbdc71 --- /dev/null +++ b/net/edf/encode_ptr_test.go @@ -0,0 +1,417 @@ +package edf + +import ( + "fmt" + "reflect" + "testing" + + "ergo.services/ergo/lib" +) + +// Basic pointer tests + +func TestEncodePtrInt(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + ptr := &v + + // type descriptor: [edtType][len=2][edtPtr][edtInt] + // value: [edtPtr][8 bytes for int64] + expect := []byte{ + edtType, 0, 2, // type header + edtPtr, edtInt, // type descriptor + edtPtr, // non-nil marker + 0, 0, 0, 0, 0, 0, 0, 42, // int value (big endian) + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrIntNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *int = nil + + // type descriptor: [edtType][len=2][edtPtr][edtInt] + // value: [edtNil] + expect := []byte{ + edtType, 0, 2, // type header + edtPtr, edtInt, // type descriptor + edtNil, // nil marker + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrString(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + s := "hello" + ptr := &s + + // type descriptor: [edtType][len=2][edtPtr][edtString] + // value: [edtPtr][len][string bytes] + expect := []byte{ + edtType, 0, 2, // type header + edtPtr, edtString, // type descriptor + edtPtr, // non-nil marker + 0, 5, // string len + 'h', 'e', 'l', 'l', 'o', + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrStringNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *string = nil + + expect := []byte{ + edtType, 0, 2, + edtPtr, edtString, + edtNil, + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrFloat64(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + f := 3.14 + ptr := &f + + expect := []byte{ + edtType, 0, 2, + edtPtr, edtFloat64, + edtPtr, + 0x40, 0x09, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f, // 3.14 in IEEE 754 + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrFloat64Nil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *float64 = nil + + expect := []byte{ + edtType, 0, 2, + edtPtr, edtFloat64, + edtNil, + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrBool(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := true + ptr := &v + + expect := []byte{ + edtType, 0, 2, + edtPtr, edtBool, + edtPtr, + 1, // true + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodePtrBoolNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var ptr *bool = nil + + expect := []byte{ + edtType, 0, 2, + edtPtr, edtBool, + edtNil, + } + + if err := Encode(ptr, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +// Nested pointer (error case) + +func TestEncodePtrPtrInt(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + ptr := &v + ptrptr := &ptr + + err := Encode(ptrptr, b, Options{}) + if err == nil { + t.Fatal("expected error for nested pointer") + } +} + +// Slice of pointers + +func TestEncodeSlicePtr(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + a, b2, c := 1, 2, 3 + slice := []*int{&a, nil, &b2, nil, &c} + + // type: [edtType][len=3][edtSlice][edtPtr][edtInt] + // value: [edtSlice][count=5][ptr][1][nil][ptr][2][nil][ptr][3] + expect := []byte{ + edtType, 0, 3, + edtSlice, edtPtr, edtInt, + edtSlice, + 0, 0, 0, 5, // count + edtPtr, 0, 0, 0, 0, 0, 0, 0, 1, // &a + edtNil, // nil + edtPtr, 0, 0, 0, 0, 0, 0, 0, 2, // &b2 + edtNil, // nil + edtPtr, 0, 0, 0, 0, 0, 0, 0, 3, // &c + } + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodeSlicePtrEmpty(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + slice := []*int{} + + expect := []byte{ + edtType, 0, 3, + edtSlice, edtPtr, edtInt, + edtSlice, + 0, 0, 0, 0, // count = 0 + } + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +func TestEncodeSlicePtrNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + var slice []*int = nil + + expect := []byte{ + edtType, 0, 3, + edtSlice, edtPtr, edtInt, + edtNil, // nil slice + } + + if err := Encode(slice, b, Options{}); err != nil { + t.Fatal(err) + } + if reflect.DeepEqual(b.B, expect) == false { + fmt.Printf("exp %#v\n", expect) + fmt.Printf("got %#v\n", b.B) + t.Fatal("incorrect value") + } +} + +// Map with pointer values + +func TestEncodeMapPtrValue(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + m := map[string]*int{"key": &v} + + if err := Encode(m, b, Options{}); err != nil { + t.Fatal(err) + } + + // verify by decoding + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dm, ok := decoded.(map[string]*int) + if ok == false { + t.Fatalf("expected map[string]*int, got %T", decoded) + } + if dm["key"] == nil || *dm["key"] != 42 { + t.Fatal("incorrect decoded value") + } +} + +func TestEncodeMapPtrValueNil(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + v := 42 + m := map[string]*int{"a": &v, "b": nil} + + if err := Encode(m, b, Options{}); err != nil { + t.Fatal(err) + } + + // verify by decoding + decoded, _, err := Decode(b.B, Options{}) + if err != nil { + t.Fatal(err) + } + + dm, ok := decoded.(map[string]*int) + if ok == false { + t.Fatalf("expected map[string]*int, got %T", decoded) + } + if dm["a"] == nil || *dm["a"] != 42 { + t.Fatal("incorrect decoded value for key 'a'") + } + if dm["b"] != nil { + t.Fatal("expected nil for key 'b'") + } +} + +// Max depth protection test + +// createNestedPointer creates N levels of pointer nesting without cycles +// e.g., depth=3 creates: *any -> *any -> *any -> int(42) +func createNestedPointer(depth int) any { + if depth == 0 { + return 42 + } + inner := createNestedPointer(depth - 1) + return &inner +} + +func TestEncodePtrMaxDepthError(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + // Build deeply nested pointer chain: 101 levels of *any + // This exceeds maxEncodeDepth (100) + val := createNestedPointer(101) + + err := Encode(val, b, Options{}) + if err == nil { + t.Fatal("expected error for max depth exceeded") + } + if err != ErrMaxDepthExceeded { + t.Fatalf("expected ErrMaxDepthExceeded, got: %v", err) + } +} + +func TestEncodePtrCustomMaxDepth(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + // Build 10 levels of nesting (no cycles) + val := createNestedPointer(10) + + // Should fail with MaxDepth=5 + err := Encode(val, b, Options{MaxDepth: 5}) + if err != ErrMaxDepthExceeded { + t.Fatalf("expected ErrMaxDepthExceeded with MaxDepth=5, got: %v", err) + } + + // Should succeed with MaxDepth=15 + b.Reset() + err = Encode(val, b, Options{MaxDepth: 15}) + if err != nil { + t.Fatalf("unexpected error with MaxDepth=15: %v", err) + } +} + +func TestEncodePtrCyclicReference(t *testing.T) { + b := lib.TakeBuffer() + defer lib.ReleaseBuffer(b) + + // Create cyclic reference: val points to itself + var val any = 42 + val = &val // val now contains *any pointing to val (cycle!) + + err := Encode(val, b, Options{}) + if err != ErrMaxDepthExceeded { + t.Fatalf("expected ErrMaxDepthExceeded for cyclic reference, got: %v", err) + } +} diff --git a/net/edf/pools.go b/net/edf/pools.go index 711cdeaa4..c934bd48d 100644 --- a/net/edf/pools.go +++ b/net/edf/pools.go @@ -25,6 +25,7 @@ func getPooledStateEncode(options Options) *stateEncode { state := stateEncodePool.Get().(*stateEncode) // Reset state to clean condition state.child = nil + state.depth = 0 state.encodeType = false state.options = options return state diff --git a/version.go b/version.go index c68b71b24..8eccdce3d 100644 --- a/version.go +++ b/version.go @@ -5,7 +5,7 @@ import "ergo.services/ergo/gen" var ( FrameworkVersion = gen.Version{ Name: "Ergo Framework", - Release: "3.2.0", + Release: "3.3.0-development", License: gen.LicenseMIT, } ) From 161afb706151b8a5596fcaad46d0ca17b1ee3af7 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 12 Feb 2026 09:52:07 +0100 Subject: [PATCH 002/122] preserve Behavior name in logger when process registers name --- node/process.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/process.go b/node/process.go index 596612144..605763257 100644 --- a/node/process.go +++ b/node/process.go @@ -339,7 +339,7 @@ func (p *process) RegisterName(name gen.Atom) error { return err } - p.log.setSource(gen.MessageLogProcess{Node: p.node.name, PID: p.pid, Name: p.name}) + p.log.setSource(gen.MessageLogProcess{Node: p.node.name, PID: p.pid, Name: p.name, Behavior: p.sbehavior}) return nil } From 8c6de25d32c1f9d467721fe529065b89b6ccb899 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 12 Feb 2026 12:39:04 +0100 Subject: [PATCH 003/122] update README.md --- CHANGELOG.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8de25ce8f..60ff8d61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### [v3.3.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.330) 2026-xx-xx [tag version v1.999.330] #### * Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation +* Fixed logger to preserve Behavior name when process registers name #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index 50d54b234..0489add4c 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. #### [v3.3.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.330) 2026-xx-xx [tag version v1.999.330] #### * Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation +* Fixed logger to preserve Behavior name when process registers name ### Development and debugging ### From 5f79c98f360e27efa2889e401855a2930b337dc8 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 13 Feb 2026 14:51:12 +0100 Subject: [PATCH 004/122] fix cleanupProcess to terminate routes after registered name and aliases cleanup --- node/node.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/node/node.go b/node/node.go index 2483f7c0c..91300d6b8 100644 --- a/node/node.go +++ b/node/node.go @@ -2326,8 +2326,6 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra // Does NOT call waitprocesses.Done() - caller must handle if needed. func (n *node) cleanupProcess(p *process, reason error) { n.processes.Delete(p.pid) - n.RouteTerminatePID(p.pid, reason) // calls TerminatedTargetPID internally - n.targets.TerminatedProcess(p.pid, reason) n.log.Trace("...cleanupProcess %s", p.pid) @@ -2342,6 +2340,9 @@ func (n *node) cleanupProcess(p *process, reason error) { n.RouteTerminateAlias(a, reason) } + n.RouteTerminatePID(p.pid, reason) // calls TerminatedTargetPID internally + n.targets.TerminatedProcess(p.pid, reason) + p.metas.Range(func(_, v any) bool { m := v.(*meta) qm := gen.TakeMailboxMessage() From 5b94204a802dcbf72d8ed15bf546748c17f04050 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Sat, 14 Feb 2026 08:46:11 +0100 Subject: [PATCH 005/122] remove system metrics (metrics.ergo.serivces) --- app/system/metrics.go | 205 ------------------------------------------ app/system/sup.go | 4 - 2 files changed, 209 deletions(-) delete mode 100644 app/system/metrics.go diff --git a/app/system/metrics.go b/app/system/metrics.go deleted file mode 100644 index 9736367d2..000000000 --- a/app/system/metrics.go +++ /dev/null @@ -1,205 +0,0 @@ -package system - -import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" - "encoding/base64" - "encoding/binary" - "fmt" - "io" - "net" - "runtime" - "strconv" - "strings" - "time" - - "ergo.services/ergo/act" - "ergo.services/ergo/gen" - "ergo.services/ergo/lib" - "ergo.services/ergo/net/edf" -) - -const ( - period time.Duration = time.Second * 300 - - DISABLE_METRICS gen.Env = "disable_metrics" -) - -type MessageMetrics struct { - Name gen.Atom - Creation int64 - Uptime int64 - Arch string - OS string - NumCPU int - GoVersion string - Version string - ErgoVersion string - Commercial string -} - -func factory_metrics() gen.ProcessBehavior { - return &metrics{} -} - -type doSendMetrics struct{} - -type metrics struct { - act.Actor - cancelSend gen.CancelFunc - key []byte - block cipher.Block -} - -func (m *metrics) Init(args ...any) error { - if err := edf.RegisterTypeOf(MessageMetrics{}); err != nil { - if err != gen.ErrTaken { - return err - } - } - - if _, disabled := m.Env(DISABLE_METRICS); disabled { - if comm := m.Node().Commercial(); len(comm) == 0 { - m.Log().Trace("metrics disabled") - return nil - } - m.Log().Trace("a commercial package is used. enforce sending metrics") - } - - m.key = []byte(lib.RandomString(32)) - b, err := aes.NewCipher(m.key) - if err != nil { - return nil - } - m.block = b - - m.Log().Trace("scheduled sending metrics in %v", period) - m.cancelSend, _ = m.SendAfter(m.PID(), doSendMetrics{}, period) - return nil -} - -func (m *metrics) HandleMessage(from gen.PID, message any) error { - - switch message.(type) { - case doSendMetrics: - m.send() - m.Log().Trace("scheduled sending metrics in %v", period) - m.cancelSend, _ = m.SendAfter(m.PID(), doSendMetrics{}, period) - - default: - m.Log().Trace("received unknown message: %#v", message) - } - return nil -} - -func (m *metrics) Terminate(reason error) { - if m.cancelSend == nil { - return - } - m.cancelSend() -} - -func (m *metrics) send() { - var msrv = "metrics.ergo.services" - - values, err := net.LookupTXT(msrv) - if err != nil || len(values) == 0 { - m.Log().Trace("lookup TXT record in %s failed or returned empty result", msrv) - return - } - v, err := base64.StdEncoding.DecodeString(values[0]) - if err != nil { - return - } - - pk, err := x509.ParsePKCS1PublicKey([]byte(v)) - if err != nil { - m.Log().Trace("unable to parse public key (TXT record in %s)", msrv) - return - } - - _, srv, err := net.LookupSRV("data", "mt1", msrv) - if err != nil || len(srv) == 0 { - m.Log().Trace("unable to resolve SRV record: %s", err) - return - } - - dsn := net.JoinHostPort(strings.TrimSuffix(srv[0].Target, "."), - strconv.Itoa(int(srv[0].Port))) - c, err := net.Dial("udp", dsn) - if err != nil { - m.Log().Trace("unable to dial the host %s: %s", dsn, err) - return - } - defer c.Close() - - msg := MessageMetrics{ - Name: m.Node().Name(), - Creation: m.Node().Creation(), - Uptime: m.Node().Uptime(), - Arch: runtime.GOARCH, - OS: runtime.GOOS, - NumCPU: runtime.NumCPU(), - GoVersion: runtime.Version(), - Version: m.Node().Version().String(), - ErgoVersion: m.Node().FrameworkVersion().String(), - Commercial: fmt.Sprintf("%v", m.Node().Commercial()), - } - - buf := lib.TakeBuffer() - defer lib.ReleaseBuffer(buf) - - hash := sha256.New() - cipher, err := rsa.EncryptOAEP(hash, rand.Reader, pk, m.key, nil) - if err != nil { - m.Log().Trace("unable to encrypt metrics message: %s (len: %d)", err, buf.Len()) - return - } - - // 2 (magic: 1144) + 2 (length) + len(cipher) - buf.Allocate(4) - buf.Append(cipher) - binary.BigEndian.PutUint16(buf.B[0:2], uint16(1144)) - binary.BigEndian.PutUint16(buf.B[2:4], uint16(len(cipher))) - - // encrypt payload and append to the buf - payload := lib.TakeBuffer() - defer lib.ReleaseBuffer(payload) - if err := edf.Encode(msg, payload, edf.Options{}); err != nil { - m.Log().Trace("unable to encode metrics message: %s", err) - return - } - - x := encrypt(payload.B, m.block) - if x == nil { - return - } - buf.Append(x) - - if _, err := c.Write(buf.B); err != nil { - m.Log().Trace("unable to send metrics: %s", err) - } - m.Log().Trace("sent metrics to %s", dsn) -} - -func encrypt(data []byte, block cipher.Block) []byte { - l := len(data) - padding := aes.BlockSize - l%aes.BlockSize - padtext := bytes.Repeat([]byte{byte(padding)}, padding) - data = append(data, padtext...) - l = len(data) - - x := make([]byte, aes.BlockSize+l) - iv := x[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil - } - cfb := cipher.NewCFBEncrypter(block, iv) - cfb.XORKeyStream(x[aes.BlockSize:], data) - return x -} diff --git a/app/system/sup.go b/app/system/sup.go index 7254d190b..1fae1de87 100644 --- a/app/system/sup.go +++ b/app/system/sup.go @@ -19,10 +19,6 @@ func (s *sup) Init(args ...any) (act.SupervisorSpec, error) { spec := act.SupervisorSpec{ Type: act.SupervisorTypeOneForOne, Children: []act.SupervisorChildSpec{ - { - Factory: factory_metrics, - Name: "system_metrics", - }, { Factory: inspect.Factory, Name: inspect.Name, From 14c398f6c8293610dbe30dfe45ad32d6d0c6e099 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 17 Feb 2026 09:00:30 +0100 Subject: [PATCH 006/122] add process lifecycle counters (spawned, spawn failed, terminated) to gen.NodeInfo --- README.md | 2 ++ gen/node.go | 9 ++++++++ node/network.go | 4 +--- node/node.go | 56 ++++++++++++++++--------------------------------- 4 files changed, 30 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 50d54b234..ac9915b8a 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,8 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation +* Added **process lifecycle counters** to `NodeInfo` - `ProcessesSpawned`, `ProcessesSpawnFailed`, `ProcessesTerminated` for cumulative statistics + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at diff --git a/gen/node.go b/gen/node.go index 79dc2d728..fb6271d78 100644 --- a/gen/node.go +++ b/gen/node.go @@ -726,6 +726,15 @@ type NodeInfo struct { // ProcessesZombee is the number of killed processes (Zombee state). ProcessesZombee int64 + // ProcessesSpawned is the cumulative number of successfully spawned processes. + ProcessesSpawned uint64 + + // ProcessesSpawnFailed is the cumulative number of failed spawn attempts. + ProcessesSpawnFailed uint64 + + // ProcessesTerminated is the cumulative number of terminated processes. + ProcessesTerminated uint64 + // RegisteredAliases is the total number of registered aliases. RegisteredAliases int64 diff --git a/node/network.go b/node/network.go index cf5bd486c..cea475655 100644 --- a/node/network.go +++ b/node/network.go @@ -904,8 +904,6 @@ func (n *network) start(options gen.NetworkOptions) error { n.registrar = registrar.Create(registrar.Options{}) } - n.node.validateLicenses(n.registrar.Version()) - if options.Cookie == "" { n.node.log.Warning("cookie is empty (gen.NetworkOptions), used randomized value") options.Cookie = lib.RandomString(16) @@ -1036,7 +1034,7 @@ func (n *network) start(options gen.NetworkOptions) error { HandshakeVersion: acceptor.handshake.Version(), ProtoVersion: acceptor.proto.Version(), } - n.node.validateLicenses(r.HandshakeVersion, r.ProtoVersion) + if a.Registrar == nil { acceptor.registrar_info = n.registrar.Info routes = append(routes, r) diff --git a/node/node.go b/node/node.go index 2483f7c0c..7c530a241 100644 --- a/node/node.go +++ b/node/node.go @@ -102,6 +102,10 @@ type node struct { enableCTRLC atomic.Bool ctrlc chan os.Signal + + processesSpawned uint64 + processesSpawnFailed uint64 + processesTerminated uint64 } type eventOwner struct { @@ -191,8 +195,6 @@ func Start(name gen.Atom, options gen.NodeOptions, frameworkVersion gen.Version) node.LoggerAdd(lo.Name, lo.Logger, lo.Filter...) } - node.validateLicenses(node.version) - // create target manager (pub/sub subsystem) before network start // because registrar may call RegisterEvent during network initialization node.targets = tm.Create(createTMBridge(node), tm.Options{}) @@ -698,6 +700,10 @@ func (n *node) Info() (gen.NodeInfo, error) { return true }) + info.ProcessesSpawned = atomic.LoadUint64(&n.processesSpawned) + info.ProcessesSpawnFailed = atomic.LoadUint64(&n.processesSpawnFailed) + info.ProcessesTerminated = atomic.LoadUint64(&n.processesTerminated) + n.names.Range(func(_, _ any) bool { info.RegisteredNames++ return true @@ -2103,10 +2109,12 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra } if factory == nil { + atomic.AddUint64(&n.processesSpawnFailed, 1) return empty, gen.ErrIncorrect } if options.ParentPID == empty || options.ParentLeader == empty { + atomic.AddUint64(&n.processesSpawnFailed, 1) return empty, gen.ErrParentUnknown } @@ -2124,6 +2132,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra if options.Register != "" { if _, exist := n.names.LoadOrStore(options.Register, p); exist { + atomic.AddUint64(&n.processesSpawnFailed, 1) return p.pid, gen.ErrTaken } p.name = options.Register @@ -2197,6 +2206,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra behavior := factory() if behavior == nil { n.names.Delete(p.name) + atomic.AddUint64(&n.processesSpawnFailed, 1) return p.pid, errors.New("factory function must return non nil value") } p.behavior = behavior @@ -2230,6 +2240,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra if p.registered.Load() { n.names.Delete(p.name) } + atomic.AddUint64(&n.processesSpawnFailed, 1) return p.pid, gen.ErrTimeout } @@ -2276,6 +2287,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra if atomic.CompareAndSwapInt32(&completed, 0, 2) { // we won - goroutine will do cleanup when ProcessInit completes n.Kill(p.pid) + atomic.AddUint64(&n.processesSpawnFailed, 1) return p.pid, gen.ErrTimeout } // goroutine won - receive result @@ -2300,6 +2312,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra } p.behavior.ProcessTerminate(initErr) }() + atomic.AddUint64(&n.processesSpawnFailed, 1) return p.pid, initErr } @@ -2319,6 +2332,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra // so we should run this process to make sure this message is handled p.run() + atomic.AddUint64(&n.processesSpawned, 1) return p.pid, nil } @@ -2360,6 +2374,8 @@ func (n *node) cleanupProcess(p *process, reason error) { func (n *node) unregisterProcess(p *process, reason error) { n.cleanupProcess(p, reason) + atomic.AddUint64(&n.processesTerminated, 1) + if p.application != system.Name { n.waitprocesses.Done() } @@ -2434,39 +2450,3 @@ func (n *node) unregisterEvent(name gen.Atom, pid gen.PID) error { return n.targets.UnregisterEvent(pid, name) } - -func (n *node) validateLicenses(versions ...gen.Version) { - for _, version := range versions { - switch version.License { - case gen.LicenseMIT: - continue - - case "": - if lib.Trace() { - n.Log().Trace("undefined license for %s", version) - } - continue - - case gen.LicenseBSL1: - var valid bool - - if _, exist := n.licenses.LoadOrStore(version, valid); exist { - continue - } - - // TODO validate license - //if valid { - // continue - //} - - n.Log().Warning("%s is distributed under %q and can not be used "+ - "without a license for production/commercial purposes", - version, version.License) - - default: - if lib.Trace() { - n.Log().Trace("unhandled license %q for %s", version.License, version) - } - } - } -} From 999ee400e5de4f1933736b2c9c659073fc375561 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 17 Feb 2026 13:08:59 +0100 Subject: [PATCH 007/122] update docs: actor metrics --- docs/extra-library/actors/metrics.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index aa1771534..c7733844a 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -126,10 +126,14 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_processes_total` | Gauge | Total number of processes including running, idle, and zombie. High counts suggest process leaks or inefficient cleanup. | | `ergo_processes_running` | Gauge | Processes actively handling messages. Low relative to total suggests most processes are idle (good) or blocked (bad - investigate what they're waiting for). | | `ergo_processes_zombie` | Gauge | Processes terminated but not yet fully cleaned up. These should be transient. Persistent zombies indicate bugs in termination handling. | +| `ergo_processes_spawned_total` | Gauge | Cumulative number of successfully spawned processes since node start. Monotonically increasing counter useful for tracking spawn rate over time. | +| `ergo_processes_spawn_failed_total` | Gauge | Cumulative number of failed spawn attempts. Non-zero values indicate initialization errors or resource constraints preventing process creation. | +| `ergo_processes_terminated_total` | Gauge | Cumulative number of terminated processes. Compare to spawned count to understand process lifecycle patterns. | | `ergo_memory_used_bytes` | Gauge | Total memory obtained from OS (uses `runtime.MemStats.Sys`). | | `ergo_memory_alloc_bytes` | Gauge | Bytes of allocated heap objects (uses `runtime.MemStats.Alloc`). | | `ergo_cpu_user_seconds` | Gauge | CPU time spent executing user code. Increases as the node does work. Rate of change indicates CPU utilization. | | `ergo_cpu_system_seconds` | Gauge | CPU time spent in kernel (system calls). High system time relative to user time suggests I/O bottlenecks or excessive syscalls. | +| `ergo_cpu_cores` | Gauge | Number of CPU cores available to the process. Useful for normalizing CPU utilization metrics. | | `ergo_applications_total` | Gauge | Number of applications loaded. Should match your expected count. Unexpected changes indicate applications starting or stopping. | | `ergo_applications_running` | Gauge | Applications currently active. Compare to total to identify stopped or failed applications. | | `ergo_registered_names_total` | Gauge | Processes registered with atom names. High counts suggest heavy use of named processes for routing. | From c99433811aa6284b8ffe324fc358d41b108eb1b2 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 18 Feb 2026 10:12:35 +0100 Subject: [PATCH 008/122] docs: update actors/metrics --- docs/extra-library/actors/metrics.md | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index aa1771534..68d8e345d 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -126,10 +126,14 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_processes_total` | Gauge | Total number of processes including running, idle, and zombie. High counts suggest process leaks or inefficient cleanup. | | `ergo_processes_running` | Gauge | Processes actively handling messages. Low relative to total suggests most processes are idle (good) or blocked (bad - investigate what they're waiting for). | | `ergo_processes_zombie` | Gauge | Processes terminated but not yet fully cleaned up. These should be transient. Persistent zombies indicate bugs in termination handling. | +| `ergo_processes_spawned_total` | Gauge | Cumulative count of successfully spawned processes since node start. Use `rate()` in Prometheus to calculate spawn rate. Sudden spikes may indicate restart loops. | +| `ergo_processes_spawn_failed_total` | Gauge | Cumulative count of failed spawn attempts. Non-zero values signal resource exhaustion or configuration errors. Should remain zero under normal operation. | +| `ergo_processes_terminated_total` | Gauge | Cumulative count of terminated processes. Compare with spawn rate to understand process lifecycle. Termination rate consistently exceeding spawn rate means the node is draining. | | `ergo_memory_used_bytes` | Gauge | Total memory obtained from OS (uses `runtime.MemStats.Sys`). | | `ergo_memory_alloc_bytes` | Gauge | Bytes of allocated heap objects (uses `runtime.MemStats.Alloc`). | | `ergo_cpu_user_seconds` | Gauge | CPU time spent executing user code. Increases as the node does work. Rate of change indicates CPU utilization. | | `ergo_cpu_system_seconds` | Gauge | CPU time spent in kernel (system calls). High system time relative to user time suggests I/O bottlenecks or excessive syscalls. | +| `ergo_cpu_cores` | Gauge | Number of CPU cores available to the runtime. Used to normalize CPU metrics - divide CPU seconds rate by core count to get utilization percentage. | | `ergo_applications_total` | Gauge | Number of applications loaded. Should match your expected count. Unexpected changes indicate applications starting or stopping. | | `ergo_applications_running` | Gauge | Applications currently active. Compare to total to identify stopped or failed applications. | | `ergo_registered_names_total` | Gauge | Processes registered with atom names. High counts suggest heavy use of named processes for routing. | @@ -299,6 +303,39 @@ Prometheus fetches `/metrics` every 15 seconds, parses the text format, and stor For dynamic discovery in Kubernetes or cloud environments, use Prometheus service discovery instead of static targets. The metrics actor itself doesn't need to know about Prometheus - it just exposes an HTTP endpoint. +## Grafana Dashboard + +The metrics package includes a pre-built Grafana dashboard (`ergo-cluster.json`) designed for monitoring Ergo clusters. The dashboard provides a comprehensive view of cluster health with automatic refresh every 10 seconds. + +### Importing the Dashboard + +1. Open Grafana and navigate to Dashboards +2. Click "Import" +3. Upload the `ergo-cluster.json` file from the metrics package or paste its contents +4. Select your Prometheus data source + +The dashboard includes a `$node` variable dropdown that filters all panels by selected nodes. By default, all nodes are displayed. + +### Understanding the Panels + +The dashboard organizes metrics into logical groups that answer operational questions: + +**Summary Row** - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. A gap between total and running processes indicates idle capacity or blocked processes. Non-zero zombies require investigation. + +**Processes** - Two timeseries showing per-node process counts over time. Steady growth without plateau suggests process leaks. Compare running counts across nodes to identify load imbalance. + +**Process Lifecycle** - Spawn and termination rates per node. The spawn panel shows both successful spawns and failures (in red). Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. When spawn exceeds termination, process count grows. + +**CPU** - User and system CPU time normalized by core count, displayed as percentages. High user CPU means compute-bound workload. High system CPU relative to user suggests excessive I/O or syscalls rather than application work. + +**Memory** - OS-reported memory and Go runtime allocation over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. + +**Network** - Four panels covering cluster totals and per-node breakdowns for message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. + +**Network Detail** - Message and byte rates between specific node pairs. Useful for tracing inter-node communication paths and identifying saturated links. + +**Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). + ## Observer Integration The metrics actor includes built-in Observer support via `HandleInspect()`. When you inspect it in Observer UI (http://localhost:9911), you see: From 3707e3863a96635cc906efe48581f1fe059f4248 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 18 Feb 2026 17:30:03 +0100 Subject: [PATCH 009/122] fix: correct PortRange logic --- gen/network.go | 11 ++++++----- node/network.go | 9 ++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gen/network.go b/gen/network.go index 3d665191b..ca3e1239d 100644 --- a/gen/network.go +++ b/gen/network.go @@ -539,13 +539,14 @@ type AcceptorOptions struct { Host string // Port is the TCP port number for incoming connections. - // Default: 15000 if not specified. + // Default: 11144 if not specified. Port uint16 - // PortRange defines the range of ports to try if Port is unavailable. - // Attempts ports from Port to (Port + PortRange). - // Example: Port=15000, PortRange=10 tries 15000-15010. - // Useful for avoiding port conflicts. + // PortRange defines how many ports to try starting from Port. + // Default (0): tries all ports from Port to 65535. + // PortRange=1: tries only the Port itself. + // PortRange=N (N>1): tries N ports starting from Port. + // Example: Port=11144, PortRange=10 tries 11144-11153. PortRange uint16 // RouteHost specifies the public/external host address to advertise in routes. diff --git a/node/network.go b/node/network.go index cea475655..c021037b9 100644 --- a/node/network.go +++ b/node/network.go @@ -1113,11 +1113,10 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { if pstart == 0 { pstart = gen.DefaultPort } - pend := a.PortRange - if pend == 0 { - pend = 50000 - } - if pend < pstart { + pend := uint16(65535) + if a.PortRange > 1 { + pend = pstart + a.PortRange - 1 + } else if a.PortRange == 1 { pend = pstart } From 1cae8a39b25ea9c43eca0c08a502827e6b810891 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 20 Feb 2026 12:03:33 +0100 Subject: [PATCH 010/122] add mailbox latency measurement (-tags=latency), gen.Node.ProcessRangeShortInfo --- CHANGELOG.md | 3 + README.md | 4 + docs/advanced/debugging.md | 38 ++++- docs/basics/node.md | 2 +- docs/basics/process.md | 2 + docs/extra-library/actors/metrics.md | 32 ++++ gen/node.go | 7 + gen/process.go | 38 +++++ lib/mpsc.go | 29 ++-- lib/mpsc_latency.go | 237 +++++++++++++++++++++++++++ lib/mpsc_types.go | 25 +++ node/network.go | 13 +- node/node.go | 41 +++++ testing/unit/node.go | 13 ++ 14 files changed, 457 insertions(+), 27 deletions(-) create mode 100644 lib/mpsc_latency.go create mode 100644 lib/mpsc_types.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 60ff8d61c..442cf8958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added **pointer type support** in EDF - `*int`, `*string`, `[]*T`, `map[K]*V`, pointer struct fields. Nil state preserved. Nested pointers (`**T`) not supported. Max encoding depth limit (100) prevents stack overflow on deeply nested structures. See [Network Transparency](https://docs.ergo.services/networking/network-transparency) documentation * Fixed logger to preserve Behavior name when process registers name +* Added **process lifecycle counters** to `gen.NodeInfo` - `ProcessesSpawned`, `ProcessesSpawnFailed`, `ProcessesTerminated` for cumulative statistics +* Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and latency fields to `MailboxQueues` in `ProcessInfo`. See [Debugging](https://docs.ergo.services/advanced/debugging) documentation +* Added **`Node.ProcessRangeShortInfo`** for efficient callback-based iteration over all processes with their current state. See [Metrics actor](https://docs.ergo.services/extra-library/actors/metrics) for Prometheus integration #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index d061a5f0f..8a72f37d0 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,8 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **process lifecycle counters** to `NodeInfo` - `ProcessesSpawned`, `ProcessesSpawnFailed`, `ProcessesTerminated` for cumulative statistics +* Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and `MailboxQueues` latency fields to `ProcessInfo`. Added `Node.ProcessRangeShortInfo` for efficient iteration over all processes. See [actor/metrics](https://github.com/ergo-services/actor-metrics) for Prometheus integration with histogram, top-N, and Grafana dashboard + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at @@ -164,6 +166,8 @@ This helps identify stuck processes during shutdown by matching PIDs/Aliases fro To disable panic recovery use `--tags norecover`. +To enable mailbox latency measurement use `--tags latency`. This adds a monotonic timestamp to every message pushed into the MPSC queue, allowing `QueueMPSC.Latency()` and `ProcessMailbox.Latency()` to report the age of the oldest unprocessed message. Overhead is approximately 10-25% on micro-benchmarks (LOCAL 1-1 scenario). Without the tag, `Latency()` returns -1 and there is zero overhead. + To enable trace logging level for the internals (node, network,...) use `--tags trace` and set the log level `gen.LogLevelTrace` for your node. For detailed debugging techniques, troubleshooting scenarios, and best practices, see the [Debugging](https://docs.ergo.services/advanced/debugging) documentation. diff --git a/docs/advanced/debugging.md b/docs/advanced/debugging.md index 036737a6a..acd3831df 100644 --- a/docs/advanced/debugging.md +++ b/docs/advanced/debugging.md @@ -72,6 +72,34 @@ options := gen.NodeOptions{ } ``` +### The `latency` Tag + +The `latency` tag enables mailbox latency measurement for all processes: + +```bash +go run --tags latency ./cmd +``` + +This activates: + +- **Monotonic timestamp** on every message pushed into the MPSC queue +- **`QueueMPSC.Latency()`** returns the age (in nanoseconds) of the oldest unprocessed message in the queue +- **`ProcessMailbox.Latency()`** returns the maximum latency across all four mailbox queues (Main, System, Urgent, Log) +- **`MailboxLatency` field** in `ProcessShortInfo` for per-process latency snapshots +- **`Node.ProcessRangeShortInfo()`** for efficient iteration over all processes with their latency data + +Without the tag, `Latency()` returns -1 (disabled) and there is zero runtime overhead -- no timestamps are recorded, no atomic operations are added to the message path. + +The overhead with the tag enabled is approximately 10-25% on micro-benchmarks (LOCAL 1-1 scenario with a single producer and consumer exchanging messages). In real applications with many processes, the overhead is lower because the cost is amortized across concurrent operations. + +Latency measurement answers the question "how long has the oldest message been sitting in this process's mailbox?" A high value means the process is not keeping up with incoming messages -- it is either overloaded, stuck in a long-running callback, or blocked. This is particularly useful for: + +- Identifying backpressure in actor pipelines +- Detecting stuck processes before they cause cascading failures +- Finding hotspot processes in large clusters + +For cluster-wide observability with Prometheus and Grafana, see the [Metrics actor](../extra-library/actors/metrics.md) which integrates latency data into histogram, top-N, and per-node panels when built with the `latency` tag. + ### Combining Tags Tags can be combined for comprehensive debugging: @@ -80,7 +108,13 @@ Tags can be combined for comprehensive debugging: go run --tags "pprof,norecover,trace" ./cmd ``` -This enables all debugging features simultaneously. Use this combination when investigating complex issues that span multiple subsystems. +or with latency measurement: + +```bash +go run --tags "pprof,latency" ./cmd +``` + +This enables all specified features simultaneously. Use combinations when investigating complex issues that span multiple subsystems. ## Profiler Integration @@ -347,7 +381,7 @@ Observer runs at `http://localhost:9911` by default when included in your node. Debugging actor systems requires tools that bridge the gap between logical actors and runtime goroutines. Ergo Framework provides this bridge through: -- **Build tags** that enable profiling and diagnostics without production overhead +- **Build tags** that enable profiling, diagnostics, and latency measurement without production overhead - **Goroutine labels** that link runtime goroutines to their actor (PID) and meta process (Alias) identities - **Shutdown diagnostics** that identify processes preventing clean termination - **Observer integration** for visual inspection of running systems diff --git a/docs/basics/node.md b/docs/basics/node.md index 25fa36cee..59952d52b 100644 --- a/docs/basics/node.md +++ b/docs/basics/node.md @@ -10,7 +10,7 @@ When you start a node, you're launching a complete system with several subsystem ## What a Node Provides -**Process Management** - The node tracks every process running on it. When you spawn a process, the node assigns it a unique PID, registers it in the process table, and manages its lifecycle. When a process terminates, the node cleans up its resources and notifies any processes that were linked or monitoring it. +**Process Management** - The node tracks every process running on it. When you spawn a process, the node assigns it a unique PID, registers it in the process table, and manages its lifecycle. When a process terminates, the node cleans up its resources and notifies any processes that were linked or monitoring it. The node provides `ProcessRangeShortInfo` for efficient iteration over all processes with their current state, including mailbox latency when built with `-tags=latency`. **Message Routing** - When a process sends a message, the node figures out where it needs to go. Local process? Route it directly to the mailbox. Remote process? Establish a network connection if needed and send it there. The sender doesn't need to know these details. diff --git a/docs/basics/process.md b/docs/basics/process.md index acc65dcbe..c9688ad10 100644 --- a/docs/basics/process.md +++ b/docs/basics/process.md @@ -8,6 +8,8 @@ A process is an actor - a lightweight entity that handles messages sequentially Every process has a mailbox where incoming messages wait to be processed. The mailbox contains four queues with different priorities: Urgent for critical system messages, System for framework control, Main for regular application messages, and Log for logging. When the process wakes up to handle messages, it processes them in priority order, taking from Urgent first, then System, then Main, and finally Log. +When built with `-tags=latency`, each queue tracks the age of its oldest unprocessed message. `ProcessMailbox.Latency()` returns the maximum latency across all four queues in nanoseconds, or -1 if the tag is not enabled. This helps identify processes that are falling behind on message processing. See [Debugging](../advanced/debugging.md) for details. + The process runs only when it has messages to handle. When the mailbox is empty, the process sleeps, consuming no CPU. When a message arrives, the process wakes, handles the message, and sleeps again if nothing else is waiting. This efficiency is why you can have thousands of processes in a single application. ## Identifying Processes diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 8c85a3a22..3f3dc7ab4 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -103,6 +103,7 @@ options := metrics.Options{ Host: "0.0.0.0", // Listen on all interfaces Port: 9090, // Prometheus default port CollectInterval: 5 * time.Second, // Collect every 5 seconds + LatencyTopN: 50, // Top-N processes by mailbox latency } node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) @@ -112,6 +113,8 @@ node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) **Port** should not conflict with other services. Prometheus conventionally uses `9090`, but many Ergo applications use that for other purposes. Choose a port that doesn't collide with your application's HTTP servers, Observer UI (default `9911`), or other metrics exporters. +**LatencyTopN** sets how many top processes by mailbox latency are tracked (default: 50). Only effective when built with `-tags=latency`. Higher values provide more visibility but increase Prometheus cardinality. + **CollectInterval** controls how frequently the actor queries node statistics. Shorter intervals provide more granular time-series data but increase CPU usage for collection. Longer intervals reduce overhead but miss short-lived spikes. For most applications, 10-15 seconds balances responsiveness with resource usage. Prometheus typically scrapes every 15-60 seconds, so collecting more frequently than your scrape interval wastes resources. ## Base Metrics @@ -153,6 +156,33 @@ The metrics actor automatically exposes these Prometheus metrics without any con Network metrics use labels (`node="..."`) to separate per-node data. This creates multiple time series - one per connected node. Prometheus queries can aggregate across labels or filter to specific nodes. +### Mailbox Latency Metrics + +When built with `-tags=latency`, the metrics actor automatically collects per-process mailbox latency data. This enables detection of stressed processes whose mailboxes are growing. + +```bash +go build -tags=latency ./... +``` + +Without the tag, latency measurement is disabled and no additional metrics are registered. There is zero overhead. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_mailbox_latency_seconds` | Histogram | - | Distribution of mailbox latency across all processes. Buckets: 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, 30s, 60s. | +| `ergo_mailbox_latency_max_seconds` | Gauge | - | Maximum mailbox latency across all processes on this node. When this exceeds 1 second, at least one process is significantly behind. | +| `ergo_mailbox_latency_processes` | Gauge | - | Number of processes with non-empty mailbox (latency > 0). High count relative to total processes indicates widespread backpressure. | +| `ergo_mailbox_latency_top_seconds` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by mailbox latency. Directly identifies which processes are the bottlenecks. | + +The `LatencyTopN` option (default: 50) controls how many processes appear in the top-N metric. For clusters with many nodes, consider the cardinality impact: each node contributes up to `LatencyTopN` time series for this metric. + +**Cardinality estimate** for a cluster of 500 nodes with `LatencyTopN=50`: +- Histogram: 500 x 14 series = 7,000 +- Max + Count gauges: 500 x 2 = 1,000 +- Top-N gauges: 500 x 50 = 25,000 +- Total: ~33,000 series + +The collection uses `Node.ProcessRangeShortInfo()` to iterate over all processes efficiently in a single pass, computing the histogram, max, stressed count, and top-N simultaneously using a min-heap for O(N) selection. + ## Custom Metrics Extend the metrics actor by embedding `metrics.Actor`. You register custom Prometheus collectors in `Init()` and update them via `CollectMetrics()` or `HandleMessage()`. @@ -334,6 +364,8 @@ The dashboard organizes metrics into logical groups that answer operational ques **Network Detail** - Message and byte rates between specific node pairs. Useful for tracing inter-node communication paths and identifying saturated links. +**Mailbox Latency** (collapsed row, requires `-tags=latency`) - Six panels for latency analysis. Two stat panels show cluster-wide max latency (with green/yellow/red thresholds) and stressed process count. A heatmap shows latency distribution over time. Two timeseries show max latency and stressed process count per node. A table lists the top 50 processes by latency with their PID, name, application, and behavior. When the `latency` tag is not used, these panels show "No data". + **Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). ## Observer Integration diff --git a/gen/node.go b/gen/node.go index fb6271d78..078a5e97d 100644 --- a/gen/node.go +++ b/gen/node.go @@ -108,6 +108,13 @@ type Node interface { // Returns ErrNodeTerminated in other states. ProcessListShortInfo(start, limit int) ([]ProcessShortInfo, error) + // ProcessRangeShortInfo iterates over all processes calling fn for each. + // The callback receives ProcessShortInfo and returns true to continue + // or false to stop iteration. + // Available in: Running state only. + // Returns ErrNodeTerminated in other states. + ProcessRangeShortInfo(fn func(ProcessShortInfo) bool) error + // ProcessName returns the registered name for the given PID. // Returns empty Atom if the process has no registered name. // Available in: Running state only. diff --git a/gen/process.go b/gen/process.go index a356c9fa6..c3eb9bc75 100644 --- a/gen/process.go +++ b/gen/process.go @@ -1014,6 +1014,11 @@ type ProcessShortInfo struct { // MessagesMailbox is the total number of messages currently in mailbox queues. MessagesMailbox uint64 + // MailboxLatency is the maximum latency across all mailbox queues (nanoseconds). + // Returns -1 if built without -tags=latency (measurement disabled). + // Returns 0 if all queues are empty. + MailboxLatency int64 + // RunningTime is the cumulative time spent in Running state (nanoseconds). RunningTime uint64 @@ -1083,6 +1088,26 @@ func (pm ProcessMailbox) Len() int64 { return pm.Main.Len() + pm.System.Len() + pm.Urgent.Len() + pm.Log.Len() } +// Latency returns the maximum latency across all mailbox queues (nanoseconds). +// Returns -1 if built without -tags=latency (measurement disabled). +// Returns 0 if all queues are empty. +func (pm ProcessMailbox) Latency() int64 { + lat := pm.Main.Latency() + if lat < 0 { + return -1 + } + if l := pm.System.Latency(); l > lat { + lat = l + } + if l := pm.Urgent.Latency(); l > lat { + lat = l + } + if l := pm.Log.Latency(); l > lat { + lat = l + } + return lat +} + // MailboxQueues contains message counts for each mailbox queue. // Part of ProcessInfo and ProcessShortInfo. // Represents a snapshot of mailbox load at the time of query. @@ -1099,4 +1124,17 @@ type MailboxQueues struct { // Log is the number of logging messages in the Log queue. Log int64 + + // LatencyMain is the latency of the oldest message in the Main queue (nanoseconds). + // Returns -1 if built without -tags=latency. + LatencyMain int64 + + // LatencySystem is the latency of the oldest message in the System queue (nanoseconds). + LatencySystem int64 + + // LatencyUrgent is the latency of the oldest message in the Urgent queue (nanoseconds). + LatencyUrgent int64 + + // LatencyLog is the latency of the oldest message in the Log queue (nanoseconds). + LatencyLog int64 } diff --git a/lib/mpsc.go b/lib/mpsc.go index ed69c050e..38ff6da5f 100644 --- a/lib/mpsc.go +++ b/lib/mpsc.go @@ -1,3 +1,5 @@ +//go:build !latency + // High-performance lock-free implementation of MPSC queue (Multiple Producers Single Consumer) package lib @@ -24,19 +26,6 @@ type queueLimitMPSC struct { lock uint32 } -type QueueMPSC interface { - Push(value any) bool - Pop() (any, bool) - Item() ItemMPSC - // Len returns the number of items in the queue - Len() int64 - // Size returns the limit for the queue. -1 - for unlimited - Size() int64 - - Lock() bool - Unlock() bool -} - func NewQueueMPSC() QueueMPSC { emptyItem := &itemMPSC{} return &queueMPSC{ @@ -62,12 +51,6 @@ func NewQueueLimitMPSC(limit int64, flush bool) QueueMPSC { } } -type ItemMPSC interface { - Next() ItemMPSC - Value() any - Clear() -} - type itemMPSC struct { value any next *itemMPSC @@ -137,6 +120,10 @@ func (q *queueMPSC) Size() int64 { return -1 // unlimited } +func (q *queueMPSC) Latency() int64 { + return -1 +} + func (q *queueMPSC) Lock() bool { return atomic.SwapUint32(&q.lock, 1) == 0 } @@ -154,6 +141,10 @@ func (q *queueLimitMPSC) Size() int64 { return q.limit } +func (q *queueLimitMPSC) Latency() int64 { + return -1 +} + func (q *queueLimitMPSC) Lock() bool { return atomic.SwapUint32(&q.lock, 1) == 0 } diff --git a/lib/mpsc_latency.go b/lib/mpsc_latency.go new file mode 100644 index 000000000..e8d3c739f --- /dev/null +++ b/lib/mpsc_latency.go @@ -0,0 +1,237 @@ +//go:build latency + +// High-performance lock-free MPSC queue with head-of-line latency measurement. +// Latency() returns how long the oldest item has been sitting in the queue. + +package lib + +import ( + "math" + "sync/atomic" + "unsafe" + _ "unsafe" +) + +//go:linkname nanotime runtime.nanotime +func nanotime() int64 + +type queueMPSCLatency struct { + head *itemMPSCLatency + tail *itemMPSCLatency + length int64 + oldest int64 // nanotime of the oldest item (head of queue) + lock uint32 +} + +type queueLimitMPSCLatency struct { + head *itemMPSCLatency + tail *itemMPSCLatency + length int64 + oldest int64 + limit int64 + flush bool + lock uint32 +} + +type itemMPSCLatency struct { + value any + next *itemMPSCLatency + pushed int64 +} + +func NewQueueMPSC() QueueMPSC { + emptyItem := &itemMPSCLatency{} + return &queueMPSCLatency{ + head: emptyItem, + tail: emptyItem, + } +} + +// NewQueueLimitMPSC creates MPSC queue with limited length and latency measurement. +// Enabling "flush" option makes this queue flush out the tail item if the limit has been reached. +// Warning: enabled "flush" option also makes this queue unusable +// for the concurrent environment +func NewQueueLimitMPSC(limit int64, flush bool) QueueMPSC { + if limit < 1 { + limit = math.MaxInt64 + } + emptyItem := &itemMPSCLatency{} + return &queueLimitMPSCLatency{ + limit: limit, + flush: flush, + head: emptyItem, + tail: emptyItem, + } +} + +// +// queueMPSCLatency +// + +func (q *queueMPSCLatency) Push(value any) bool { + i := &itemMPSCLatency{ + value: value, + pushed: nanotime(), + } + atomic.AddInt64(&q.length, 1) + old_head := (*itemMPSCLatency)(atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.head)), unsafe.Pointer(i))) + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&old_head.next)), unsafe.Pointer(i)) + atomic.CompareAndSwapInt64(&q.oldest, 0, i.pushed) + return true +} + +func (q *queueMPSCLatency) Pop() (any, bool) { + tail := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)))) + tail_next := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail.next)))) + if tail_next == nil { + return nil, false + } + + value := tail_next.value + tail_next.value = nil + + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)), unsafe.Pointer(tail_next)) + atomic.AddInt64(&q.length, -1) + + // update oldest: check next item in queue + next := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail_next.next)))) + if next != nil { + atomic.StoreInt64(&q.oldest, next.pushed) + } else { + atomic.StoreInt64(&q.oldest, 0) + } + + return value, true +} + +func (q *queueMPSCLatency) Latency() int64 { + ts := atomic.LoadInt64(&q.oldest) + if ts == 0 { + return 0 + } + return nanotime() - ts +} + +func (q *queueMPSCLatency) Len() int64 { + return atomic.LoadInt64(&q.length) +} + +func (q *queueMPSCLatency) Size() int64 { + return -1 +} + +func (q *queueMPSCLatency) Lock() bool { + return atomic.SwapUint32(&q.lock, 1) == 0 +} + +func (q *queueMPSCLatency) Unlock() bool { + return atomic.SwapUint32(&q.lock, 0) == 1 +} + +func (q *queueMPSCLatency) Item() ItemMPSC { + tail := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)))) + item := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail.next)))) + if item == nil { + return nil + } + return item +} + +// +// queueLimitMPSCLatency +// + +func (q *queueLimitMPSCLatency) Push(value any) bool { + if q.Len()+1 > q.limit { + if q.flush == false { + return false + } + q.Pop() + } + + i := &itemMPSCLatency{ + value: value, + pushed: nanotime(), + } + atomic.AddInt64(&q.length, 1) + old_head := (*itemMPSCLatency)(atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(&q.head)), unsafe.Pointer(i))) + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&old_head.next)), unsafe.Pointer(i)) + atomic.CompareAndSwapInt64(&q.oldest, 0, i.pushed) + return true +} + +func (q *queueLimitMPSCLatency) Pop() (any, bool) { + tail := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)))) + tail_next := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail.next)))) + if tail_next == nil { + return nil, false + } + + value := tail_next.value + tail_next.value = nil + + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)), unsafe.Pointer(tail_next)) + atomic.AddInt64(&q.length, -1) + + next := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail_next.next)))) + if next != nil { + atomic.StoreInt64(&q.oldest, next.pushed) + } else { + atomic.StoreInt64(&q.oldest, 0) + } + + return value, true +} + +func (q *queueLimitMPSCLatency) Latency() int64 { + ts := atomic.LoadInt64(&q.oldest) + if ts == 0 { + return 0 + } + return nanotime() - ts +} + +func (q *queueLimitMPSCLatency) Len() int64 { + return atomic.LoadInt64(&q.length) +} + +func (q *queueLimitMPSCLatency) Size() int64 { + return q.limit +} + +func (q *queueLimitMPSCLatency) Lock() bool { + return atomic.SwapUint32(&q.lock, 1) == 0 +} + +func (q *queueLimitMPSCLatency) Unlock() bool { + return atomic.SwapUint32(&q.lock, 0) == 1 +} + +func (q *queueLimitMPSCLatency) Item() ItemMPSC { + tail := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&q.tail)))) + item := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&tail.next)))) + if item == nil { + return nil + } + return item +} + +// +// itemMPSCLatency implements ItemMPSC +// + +func (i *itemMPSCLatency) Next() ItemMPSC { + next := (*itemMPSCLatency)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&i.next)))) + if next == nil { + return nil + } + return next +} + +func (i *itemMPSCLatency) Value() any { + return i.value +} + +func (i *itemMPSCLatency) Clear() { + i.value = nil +} diff --git a/lib/mpsc_types.go b/lib/mpsc_types.go new file mode 100644 index 000000000..04bc805b6 --- /dev/null +++ b/lib/mpsc_types.go @@ -0,0 +1,25 @@ +package lib + +type QueueMPSC interface { + Push(value any) bool + Pop() (any, bool) + Item() ItemMPSC + // Len returns the number of items in the queue + Len() int64 + // Size returns the limit for the queue. -1 - for unlimited + Size() int64 + // Latency returns how long the oldest item has been in the queue (nanoseconds). + // Safe to call from any goroutine. + // Returns -1 if built without -tags=latency (measurement disabled). + // Returns 0 if the queue is empty. + Latency() int64 + + Lock() bool + Unlock() bool +} + +type ItemMPSC interface { + Next() ItemMPSC + Value() any + Clear() +} diff --git a/node/network.go b/node/network.go index c021037b9..8a14c3438 100644 --- a/node/network.go +++ b/node/network.go @@ -1113,11 +1113,14 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { if pstart == 0 { pstart = gen.DefaultPort } - pend := uint16(65535) + pend := uint32(65535) if a.PortRange > 1 { - pend = pstart + a.PortRange - 1 + p := uint32(pstart) + uint32(a.PortRange) - 1 + if p < 65535 { + pend = p + } } else if a.PortRange == 1 { - pend = pstart + pend = uint32(pstart) } acceptor := &acceptor{ @@ -1137,7 +1140,7 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { acceptor.atom_mapping[k] = v } - for i := pstart; i < pend+1; i++ { + for i := uint32(pstart); i <= pend; i++ { hp := net.JoinHostPort(a.Host, strconv.Itoa(int(i))) lcl, err := lc.Listen(context.Background(), a.TCP, hp) if err != nil { @@ -1149,7 +1152,7 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { continue } - acceptor.port = i + acceptor.port = uint16(i) acceptor.l = lcl break } diff --git a/node/node.go b/node/node.go index ab255b238..81de1a19a 100644 --- a/node/node.go +++ b/node/node.go @@ -496,6 +496,10 @@ func (n *node) ProcessInfo(pid gen.PID) (gen.ProcessInfo, error) { info.MailboxQueues.Urgent = p.mailbox.Urgent.Len() info.MailboxQueues.System = p.mailbox.System.Len() info.MailboxQueues.Log = p.mailbox.Log.Len() + info.MailboxQueues.LatencyMain = p.mailbox.Main.Latency() + info.MailboxQueues.LatencySystem = p.mailbox.System.Latency() + info.MailboxQueues.LatencyUrgent = p.mailbox.Urgent.Latency() + info.MailboxQueues.LatencyLog = p.mailbox.Log.Latency() info.MessagesIn = atomic.LoadUint64(&p.messagesIn) info.MessagesOut = atomic.LoadUint64(&p.messagesOut) info.RunningTime = atomic.LoadUint64(&p.runningTime) @@ -784,6 +788,7 @@ func (n *node) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortInfo, e MessagesIn: process.messagesIn, MessagesOut: process.messagesOut, MessagesMailbox: uint64(messagesMailbox), + MailboxLatency: process.mailbox.Latency(), RunningTime: process.runningTime, Uptime: process.Uptime(), State: process.State(), @@ -799,6 +804,40 @@ func (n *node) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortInfo, e } +func (n *node) ProcessRangeShortInfo(fn func(gen.ProcessShortInfo) bool) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + + n.processes.Range(func(_, v any) bool { + p := v.(*process) + messagesMailbox := p.mailbox.Main.Len() + + p.mailbox.System.Len() + + p.mailbox.Urgent.Len() + + p.mailbox.Log.Len() + + info := gen.ProcessShortInfo{ + PID: p.pid, + Name: p.name, + Application: p.application, + Behavior: p.sbehavior, + MessagesIn: p.messagesIn, + MessagesOut: p.messagesOut, + MessagesMailbox: uint64(messagesMailbox), + MailboxLatency: p.mailbox.Latency(), + RunningTime: p.runningTime, + Uptime: p.Uptime(), + State: p.State(), + Parent: p.parent, + Leader: p.leader, + LogLevel: p.log.Level(), + } + return fn(info) + }) + + return nil +} + func (n *node) NetworkStart(options gen.NetworkOptions) error { if n.isRunning() == false { return gen.ErrNodeTerminated @@ -1722,6 +1761,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MessagesIn: p.messagesIn, MessagesOut: p.messagesOut, MessagesMailbox: uint64(messagesMailbox), + MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, Uptime: p.Uptime(), State: p.State(), @@ -1757,6 +1797,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MessagesIn: p.messagesIn, MessagesOut: p.messagesOut, MessagesMailbox: uint64(messagesMailbox), + MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, Uptime: p.Uptime(), State: p.State(), diff --git a/testing/unit/node.go b/testing/unit/node.go index ef78d2007..335aee78d 100644 --- a/testing/unit/node.go +++ b/testing/unit/node.go @@ -241,6 +241,19 @@ func (tn *TestNode) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortIn return infos, nil } +func (tn *TestNode) ProcessRangeShortInfo(fn func(gen.ProcessShortInfo) bool) error { + for pid := range tn.processes { + info := gen.ProcessShortInfo{ + PID: pid, + State: gen.ProcessStateRunning, + } + if fn(info) == false { + break + } + } + return nil +} + func (tn *TestNode) ProcessName(pid gen.PID) (gen.Atom, error) { // Simple stub - returns empty name return "", nil From 618f3772620494cd521f7272f43746d2948e4c3d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 20 Feb 2026 20:07:25 +0100 Subject: [PATCH 011/122] update docs --- docs/advanced/debugging.md | 2 +- docs/extra-library/actors/metrics.md | 82 +++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/docs/advanced/debugging.md b/docs/advanced/debugging.md index acd3831df..6ff16ba69 100644 --- a/docs/advanced/debugging.md +++ b/docs/advanced/debugging.md @@ -98,7 +98,7 @@ Latency measurement answers the question "how long has the oldest message been s - Detecting stuck processes before they cause cascading failures - Finding hotspot processes in large clusters -For cluster-wide observability with Prometheus and Grafana, see the [Metrics actor](../extra-library/actors/metrics.md) which integrates latency data into histogram, top-N, and per-node panels when built with the `latency` tag. +For cluster-wide observability with Prometheus and Grafana, see the [Metrics actor](../extra-library/actors/metrics.md) which integrates latency data into distribution, top-N, and per-node panels when built with the `latency` tag. ### Combining Tags diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 3f3dc7ab4..353b9aeb2 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -168,20 +168,22 @@ Without the tag, latency measurement is disabled and no additional metrics are r | Metric | Type | Labels | Description | |--------|------|--------|-------------| -| `ergo_mailbox_latency_seconds` | Histogram | - | Distribution of mailbox latency across all processes. Buckets: 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, 30s, 60s. | +| `ergo_mailbox_latency_distribution` | Gauge | `range` | Number of processes in each latency range. Snapshot per collect cycle -- values reflect the current state, not cumulative history. | | `ergo_mailbox_latency_max_seconds` | Gauge | - | Maximum mailbox latency across all processes on this node. When this exceeds 1 second, at least one process is significantly behind. | | `ergo_mailbox_latency_processes` | Gauge | - | Number of processes with non-empty mailbox (latency > 0). High count relative to total processes indicates widespread backpressure. | | `ergo_mailbox_latency_top_seconds` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by mailbox latency. Directly identifies which processes are the bottlenecks. | +The distribution metric uses gauge-based snapshots rather than a Prometheus histogram. Each collect cycle iterates over all processes, counts how many fall into each latency range, and sets the gauge values from scratch. This approach is a better fit for periodic state observation than cumulative histograms, which are designed for discrete events like HTTP requests. The ranges are: 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, 30s, 60s, and 60s+. Each range represents an upper boundary -- for example, "5ms" counts processes with latency between 1ms and 5ms. + The `LatencyTopN` option (default: 50) controls how many processes appear in the top-N metric. For clusters with many nodes, consider the cardinality impact: each node contributes up to `LatencyTopN` time series for this metric. **Cardinality estimate** for a cluster of 500 nodes with `LatencyTopN=50`: -- Histogram: 500 x 14 series = 7,000 +- Distribution: 500 x 12 series = 6,000 - Max + Count gauges: 500 x 2 = 1,000 - Top-N gauges: 500 x 50 = 25,000 -- Total: ~33,000 series +- Total: ~32,000 series -The collection uses `Node.ProcessRangeShortInfo()` to iterate over all processes efficiently in a single pass, computing the histogram, max, stressed count, and top-N simultaneously using a min-heap for O(N) selection. +The collection uses `Node.ProcessRangeShortInfo()` to iterate over all processes efficiently in a single pass, computing the distribution, max, stressed count, and top-N simultaneously using a min-heap for O(N) selection. ## Custom Metrics @@ -352,9 +354,9 @@ The dashboard organizes metrics into logical groups that answer operational ques **Summary Row** - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. A gap between total and running processes indicates idle capacity or blocked processes. Non-zero zombies require investigation. -**Processes** - Two timeseries showing per-node process counts over time. Steady growth without plateau suggests process leaks. Compare running counts across nodes to identify load imbalance. +**Mailbox Latency** (expanded row, requires `-tags=latency`) - Appears right after the Summary row. Contains six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". -**Process Lifecycle** - Spawn and termination rates per node. The spawn panel shows both successful spawns and failures (in red). Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. When spawn exceeds termination, process count grows. +**Processes** (collapsed row) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Click the row header to expand. Steady growth in total without plateau suggests process leaks. Compare running counts across nodes to identify load imbalance. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. **CPU** - User and system CPU time normalized by core count, displayed as percentages. High user CPU means compute-bound workload. High system CPU relative to user suggests excessive I/O or syscalls rather than application work. @@ -364,10 +366,74 @@ The dashboard organizes metrics into logical groups that answer operational ques **Network Detail** - Message and byte rates between specific node pairs. Useful for tracing inter-node communication paths and identifying saturated links. -**Mailbox Latency** (collapsed row, requires `-tags=latency`) - Six panels for latency analysis. Two stat panels show cluster-wide max latency (with green/yellow/red thresholds) and stressed process count. A heatmap shows latency distribution over time. Two timeseries show max latency and stressed process count per node. A table lists the top 50 processes by latency with their PID, name, application, and behavior. When the `latency` tag is not used, these panels show "No data". - **Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). +### Reading the Latency Dashboard + +The latency row is the primary tool for answering "are my actors keeping up with their workload?" It contains six panels organized in three tiers: cluster overview at the top, per-node breakdown in the middle, and detailed drill-down at the bottom. + +#### Start with the top row + +The **Max Latency** panel (left) and **Stressed Processes** panel (right) sit at the top of the latency section. Together they answer the most basic operational question: is there a problem right now? + +Max Latency shows the highest mailbox latency across all selected nodes as a red timeseries. The value represents how long the oldest unprocessed message has been sitting in some process's mailbox. Under normal conditions this stays under 100ms. Values above 1 second mean at least one process is significantly behind -- it is either overloaded, stuck in a long-running callback, or waiting for an external resource. + +Stressed Processes shows a stacked area chart with two layers. The light-blue area represents processes with latency under 1ms -- these are technically non-empty mailboxes but the delay is negligible and considered normal operation. The orange area represents processes with latency of 1ms or above -- these are the ones worth investigating. In a healthy system the orange area should be absent or thin. A growing orange area indicates that more and more processes are falling behind. + +If both panels look calm -- Max Latency under 100ms, no orange in Stressed Processes -- the system is healthy. No further investigation needed. + +#### React to these signals + +**Max Latency spikes above 1 second.** At least one process is severely behind. This is the strongest signal that something is wrong. Scroll down to the Top Stressed Processes table to identify the specific process by its application, behavior, name, and PID. + +**Orange area growing in Stressed Processes.** Multiple processes are accumulating latency. This is broader than a single stuck process -- it suggests the node or cluster is under general pressure. Look at the Latency Distribution panel to understand how the latency is spread across ranges. Check the CPU panels to see if the system is compute-bound. + +**A spike in Max Latency followed by a quick return to normal.** A temporary burst of load that the system recovered from. Compare the timing with the Process Spawn Rate panel (in the collapsed Processes row) to see if the spike correlates with a batch of new processes starting up or a restart event. + +**Max Latency persistently elevated (minutes, not seconds).** A process is stuck. It has a message in its mailbox that arrived long ago and has not been processed. This is different from overload -- overload causes latency to fluctuate with traffic, while a stuck process shows a steadily increasing or flat high value. Identify the process in the Top Stressed Processes table and investigate its behavior. + +#### Identify the node + +The middle tier contains **Max Latency per Node** (left) and **Stressed Processes per Node** (right). These panels break down the cluster-wide values into individual nodes. + +If one node shows high latency while others are calm, the problem is localized. That specific node may be overloaded, running a stuck process, or experiencing resource constraints. Cross-reference with the CPU, Memory, and Network panels for that node. + +If multiple nodes show similar latency patterns, the problem is systemic. Common causes include a shared external dependency that is slow, a distributed traffic pattern that overwhelms multiple nodes simultaneously, or a deployment issue affecting the entire cluster. + +The relationship between per-node max latency and per-node stressed count is informative. A node with high max latency but low stressed count has one problematic process while the rest are fine. A node with moderate latency but high stressed count is generally overloaded -- many processes are all slightly behind. + +#### Understand the distribution + +The **Latency Distribution** panel shows a stacked area chart where each layer represents a latency range. The color gradient runs from green (1ms, 5ms, 10ms) through yellow (50ms, 100ms) to orange (500ms, 1s) and red/dark-red (5s, 10s, 30s, 60s, 60s+). The legend is sorted from highest to lowest range. + +In a healthy system, the chart is predominantly green or empty. Processes with latency under 10ms are operating normally -- the delay is within typical scheduling jitter. + +Yellow layers (50ms-100ms) appearing during traffic spikes are acceptable if they disappear when the spike ends. Persistent yellow suggests the system is running near capacity. + +Orange and red layers indicate processes that are seriously behind. Even a thin red sliver means some process has latency measured in seconds. Look at the Top Stressed Processes table to find it. + +The distribution panel is particularly useful for distinguishing between two scenarios that look similar in the Max Latency panel: one stuck process (a single red sliver while the rest is green) versus widespread degradation (the entire chart shifting from green toward orange). The former requires investigating a specific process; the latter requires scaling or load-shedding. + +#### Find the specific process + +The **Top Stressed Processes** table at the bottom lists up to 50 processes with the highest mailbox latency across the cluster. Columns include Application, Behavior, Name, PID, Node, and Latency (plus Kubernetes labels when running in a containerized environment). The table is sorted by latency in descending order. + +This table directly answers "which process is the bottleneck?" The Application and Behavior columns tell you what kind of actor it is. The Name column gives its registered name if it has one. The Node column tells you where it runs. + +Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme latency (minutes) while others are in milliseconds points to a stuck or blocked process that needs specific investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques to identify what a stuck process is doing. + +#### Correlate with other panels + +Latency data becomes most useful when combined with other dashboard panels: + +- **High latency + high CPU** -- processes are compute-bound. The actors are doing heavy work in their callbacks and cannot keep up with the message rate. Consider distributing work across more processes or offloading expensive computation. + +- **High latency + low CPU** -- processes are blocked on something other than computation. Common causes: waiting for external I/O (database, HTTP calls), waiting for responses from other actors via synchronous calls, or contention on shared resources. + +- **High latency + growing memory** -- mailboxes are accumulating messages faster than processes can handle them. The unprocessed messages consume memory. If this continues, the node will eventually run out of memory. + +- **High latency + network traffic spike** -- a burst of remote messages is overwhelming the receiving processes. Check the Network per Node and Network Detail panels to identify which node-to-node link is responsible. + ## Observer Integration The metrics actor includes built-in Observer support via `HandleInspect()`. When you inspect it in Observer UI (http://localhost:9911), you see: From eeba36106d3f06d48e941749640fb50c357e3439 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Sat, 21 Feb 2026 13:26:45 +0100 Subject: [PATCH 012/122] update docs for actors/metrics --- docs/extra-library/actors/metrics.md | 191 +++++++++++++++++++-------- 1 file changed, 134 insertions(+), 57 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 353b9aeb2..119b88551 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -12,6 +12,10 @@ The metrics actor addresses this by tracking: **Process metrics** - How many processes exist, how many are running vs. idle vs. zombie. This reveals whether your node is under load or experiencing process leaks. +**Mailbox metrics** - Queue depth and latency for every process on the node. Depth shows how many messages are waiting in each mailbox; latency shows how long the oldest message has been waiting. Together they answer whether actors are keeping up with their workload and which specific processes are falling behind. + +**Utilization and throughput metrics** - How much time each process spends executing callbacks relative to its lifetime, and how many messages flow through the node per second. These reveal compute-bound actors, idle capacity, and overall system throughput. + **Memory metrics** - Heap allocation and actual memory used. Actor systems can accumulate small allocations across thousands of processes. Memory metrics help identify whether garbage collection keeps pace with allocation. **Network metrics** - For distributed Ergo clusters, tracking bytes and messages flowing between nodes reveals network bottlenecks, routing inefficiencies, or failing connections. @@ -54,7 +58,7 @@ When you spawn the metrics actor: 1. **HTTP endpoint starts** at the configured host and port. The `/metrics` endpoint immediately serves Prometheus-formatted data. -2. **Base metrics collect automatically**. Node information (processes, memory, CPU) and network statistics (connected nodes, message rates) update at the configured interval. +2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), and per-process metrics (mailbox depth, utilization, latency, aggregates) update at the configured interval. 3. **Custom metrics update** via `CollectMetrics()` callback or `HandleMessage()` processing, depending on your implementation. @@ -91,6 +95,7 @@ Default configuration: - **Host**: `localhost` - **Port**: `3000` - **CollectInterval**: `10 seconds` +- **TopN**: `50` The HTTP endpoint starts automatically during initialization. The first metrics collection happens immediately, and subsequent collections run at the configured interval. @@ -103,7 +108,7 @@ options := metrics.Options{ Host: "0.0.0.0", // Listen on all interfaces Port: 9090, // Prometheus default port CollectInterval: 5 * time.Second, // Collect every 5 seconds - LatencyTopN: 50, // Top-N processes by mailbox latency + TopN: 50, // Top-N processes for each metric group } node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) @@ -113,7 +118,7 @@ node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) **Port** should not conflict with other services. Prometheus conventionally uses `9090`, but many Ergo applications use that for other purposes. Choose a port that doesn't collide with your application's HTTP servers, Observer UI (default `9911`), or other metrics exporters. -**LatencyTopN** sets how many top processes by mailbox latency are tracked (default: 50). Only effective when built with `-tags=latency`. Higher values provide more visibility but increase Prometheus cardinality. +**TopN** sets how many top processes are tracked for each per-process metric group -- mailbox depth, utilization, and latency (default: 50). Higher values provide more visibility but increase Prometheus cardinality. Set to 0 is not supported; the minimum effective value is 1. **CollectInterval** controls how frequently the actor queries node statistics. Shorter intervals provide more granular time-series data but increase CPU usage for collection. Longer intervals reduce overhead but miss short-lived spikes. For most applications, 10-15 seconds balances responsiveness with resource usage. Prometheus typically scrapes every 15-60 seconds, so collecting more frequently than your scrape interval wastes resources. @@ -148,13 +153,13 @@ The metrics actor automatically exposes these Prometheus metrics without any con | Metric | Type | Labels | Description | |--------|------|--------|-------------| | `ergo_connected_nodes_total` | Gauge | - | Number of remote nodes connected. For distributed systems, this should match your expected cluster size. | -| `ergo_remote_node_uptime_seconds` | Gauge | `node` | Uptime of each connected remote node. Resets when the remote node restarts. | -| `ergo_remote_messages_in_total` | Gauge | `node` | Messages received from each remote node. Rate indicates traffic volume. | -| `ergo_remote_messages_out_total` | Gauge | `node` | Messages sent to each remote node. Asymmetric in/out rates may reveal routing issues. | -| `ergo_remote_bytes_in_total` | Gauge | `node` | Bytes received from each remote node. Disproportionate bytes-to-messages ratio suggests large messages or inefficient serialization. | -| `ergo_remote_bytes_out_total` | Gauge | `node` | Bytes sent to each remote node. Monitors network bandwidth usage per peer. | +| `ergo_remote_node_uptime_seconds` | Gauge | `remote_node` | Uptime of each connected remote node. Resets when the remote node restarts. | +| `ergo_remote_messages_in_total` | Gauge | `remote_node` | Messages received from each remote node. Rate indicates traffic volume. | +| `ergo_remote_messages_out_total` | Gauge | `remote_node` | Messages sent to each remote node. Asymmetric in/out rates may reveal routing issues. | +| `ergo_remote_bytes_in_total` | Gauge | `remote_node` | Bytes received from each remote node. Disproportionate bytes-to-messages ratio suggests large messages or inefficient serialization. | +| `ergo_remote_bytes_out_total` | Gauge | `remote_node` | Bytes sent to each remote node. Monitors network bandwidth usage per peer. | -Network metrics use labels (`node="..."`) to separate per-node data. This creates multiple time series - one per connected node. Prometheus queries can aggregate across labels or filter to specific nodes. +Network metrics use labels (`remote_node="..."`) to separate per-node data. This creates multiple time series - one per connected node. Prometheus queries can aggregate across labels or filter to specific nodes. ### Mailbox Latency Metrics @@ -175,15 +180,68 @@ Without the tag, latency measurement is disabled and no additional metrics are r The distribution metric uses gauge-based snapshots rather than a Prometheus histogram. Each collect cycle iterates over all processes, counts how many fall into each latency range, and sets the gauge values from scratch. This approach is a better fit for periodic state observation than cumulative histograms, which are designed for discrete events like HTTP requests. The ranges are: 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, 30s, 60s, and 60s+. Each range represents an upper boundary -- for example, "5ms" counts processes with latency between 1ms and 5ms. -The `LatencyTopN` option (default: 50) controls how many processes appear in the top-N metric. For clusters with many nodes, consider the cardinality impact: each node contributes up to `LatencyTopN` time series for this metric. +The `TopN` option (default: 50) controls how many processes appear in the top-N metric. The same setting applies to all per-process top-N metrics (latency, depth, utilization). + +### Mailbox Depth Metrics + +The metrics actor collects per-process mailbox queue depth -- the number of messages waiting in the mailbox at the moment of collection. While latency measures how long the oldest message has been waiting, depth measures how many messages are queued. The two metrics are complementary: a process may have high depth with low latency if it processes messages quickly but receives many at once, or low depth with high latency if a single message is taking a long time to process. + +No build tags required. Depth metrics are always active. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_mailbox_depth_distribution` | Gauge | `range` | Number of processes in each depth range. Snapshot per collect cycle. | +| `ergo_mailbox_depth_max` | Gauge | - | Maximum mailbox depth across all processes on this node. | +| `ergo_mailbox_depth_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by mailbox depth. | + +Distribution ranges: 1, 5, 10, 50, 100, 500, 1K, 5K, 10K, 10K+. Each range represents an upper boundary. Processes with empty mailboxes are not counted. -**Cardinality estimate** for a cluster of 500 nodes with `LatencyTopN=50`: -- Distribution: 500 x 12 series = 6,000 -- Max + Count gauges: 500 x 2 = 1,000 -- Top-N gauges: 500 x 50 = 25,000 -- Total: ~32,000 series +### Process Utilization Metrics -The collection uses `Node.ProcessRangeShortInfo()` to iterate over all processes efficiently in a single pass, computing the distribution, max, stressed count, and top-N simultaneously using a min-heap for O(N) selection. +The metrics actor collects per-process utilization -- the ratio of callback running time to process uptime. A process that has been alive for 100 seconds and spent 30 of those seconds inside callbacks has a utilization of 0.30 (30%). This is a lifetime average computed from cumulative counters that the framework maintains for each process. It answers the question "which actors have been busiest over their entire lifetime?" + +Utilization is not the same as current CPU load. A process that was heavily loaded an hour ago but is idle now will still show high lifetime utilization. For current load, the dashboard provides `rate(ergo_process_running_time_seconds)` which shows how much callback time is happening right now per second. + +No build tags required. Utilization metrics are always active. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_process_utilization_distribution` | Gauge | `range` | Number of processes in each utilization range. Snapshot per collect cycle. | +| `ergo_process_utilization_max` | Gauge | - | Maximum process utilization on this node. | +| `ergo_process_utilization_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by utilization. | + +Distribution ranges: 1%, 5%, 10%, 25%, 50%, 75%, 90%, 90%+. Processes with zero running time or zero uptime are excluded. Utilization is capped at 1.0 (100%). + +### Process Aggregate Metrics + +The metrics actor computes node-level aggregate counters by summing per-process values across all processes on the node. These provide a high-level view of how much work the node is doing without the cardinality cost of per-process series. + +| Metric | Type | Description | +|--------|------|-------------| +| `ergo_process_messages_in` | Gauge | Sum of messages received by all processes on this node. | +| `ergo_process_messages_out` | Gauge | Sum of messages sent by all processes on this node. | +| `ergo_process_running_time_seconds` | Gauge | Sum of callback running time across all processes on this node (seconds). | + +These are cumulative values -- apply `rate()` in Prometheus to get per-second rates. When a process terminates, its contribution is removed from the sum, which may cause the aggregate to decrease momentarily. This is expected and `rate()` handles it correctly in most cases. + +`rate(ergo_process_messages_in)` and `rate(ergo_process_messages_out)` give the node-level message throughput in messages per second. `rate(ergo_process_running_time_seconds)` gives the node-level actor CPU utilization in seconds of callback execution per second -- when this value approaches the number of available CPU cores, the node is compute-saturated. + +### Per-Process Metrics Collection + +All per-process metrics (latency, depth, utilization, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, and utilization collectors simultaneously. Top-N selection uses a min-heap for O(N) efficiency. This design ensures that adding more metric types does not multiply the number of iterations over the process table. + +### Cardinality + +For a cluster of 500 nodes with `TopN=50`: + +- Depth distribution + max + top-N: 500 x (10 + 1 + 50) = 30,500 +- Utilization distribution + max + top-N: 500 x (8 + 1 + 50) = 29,500 +- Aggregates: 500 x 3 = 1,500 +- Latency distribution + max + count + top-N: 500 x (12 + 2 + 50) = 32,000 (with `-tags=latency`) +- Total without latency: ~61,500 series +- Total with latency: ~93,500 series + +For a typical cluster of 30 nodes, the total is approximately 6,000 series (or 10,000 with latency). At a 15-second Prometheus scrape interval and default 15-day retention, this amounts to roughly 1.3 GB of disk space -- negligible for any modern monitoring setup. ## Custom Metrics @@ -249,6 +307,7 @@ type AppMetrics struct { metrics.Actor requestsTotal prometheus.Counter + errorsTotal prometheus.Counter requestLatency prometheus.Histogram } @@ -258,13 +317,18 @@ func (m *AppMetrics) Init(args ...any) (metrics.Options, error) { Help: "Total requests processed", }) + m.errorsTotal = prometheus.NewCounter(prometheus.CounterOpts{ + Name: "myapp_errors_total", + Help: "Total errors occurred", + }) + m.requestLatency = prometheus.NewHistogram(prometheus.HistogramOpts{ Name: "myapp_request_duration_seconds", Help: "Request latency distribution", Buckets: prometheus.DefBuckets, }) - m.Registry().MustRegister(m.requestsTotal, m.requestLatency) + m.Registry().MustRegister(m.requestsTotal, m.errorsTotal, m.requestLatency) return metrics.Options{Port: 9090}, nil } @@ -350,13 +414,17 @@ The dashboard includes a `$node` variable dropdown that filters all panels by se ### Understanding the Panels -The dashboard organizes metrics into logical groups that answer operational questions: +The dashboard organizes metrics into logical groups arranged from high-level overview at the top to detailed breakdowns below. Rows marked "collapsed" are hidden by default -- click the row header to expand them. + +**Summary Row** (expanded) - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. A gap between total and running processes indicates idle capacity or blocked processes. Non-zero zombies require investigation. -**Summary Row** - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. A gap between total and running processes indicates idle capacity or blocked processes. Non-zero zombies require investigation. +**Mailbox Latency** (expanded, requires `-tags=latency`) - Six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". -**Mailbox Latency** (expanded row, requires `-tags=latency`) - Appears right after the Summary row. Contains six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". +**Mailbox Depth** (collapsed) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." -**Processes** (collapsed row) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Click the row header to expand. Steady growth in total without plateau suggests process leaks. Compare running counts across nodes to identify load imbalance. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. +**Process Activity** (collapsed) - Four panels covering utilization and throughput. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Message Throughput per Node shows `rate(messages_in)` and `rate(messages_out)` per node in messages per second. Top Processes by Utilization is a table showing the busiest actors by lifetime utilization. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization. When this value approaches the available CPU core count, the node is compute-saturated. + +**Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. **CPU** - User and system CPU time normalized by core count, displayed as percentages. High user CPU means compute-bound workload. High system CPU relative to user suggests excessive I/O or syscalls rather than application work. @@ -368,71 +436,80 @@ The dashboard organizes metrics into logical groups that answer operational ques **Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). -### Reading the Latency Dashboard +### Working with the Dashboard -The latency row is the primary tool for answering "are my actors keeping up with their workload?" It contains six panels organized in three tiers: cluster overview at the top, per-node breakdown in the middle, and detailed drill-down at the bottom. +The dashboard is designed around a top-down investigation pattern. You start with high-level signals that tell you whether something is wrong, then drill into progressively more specific panels to understand what, where, and why. This section describes the investigation flow. -#### Start with the top row +#### Routine check -The **Max Latency** panel (left) and **Stressed Processes** panel (right) sit at the top of the latency section. Together they answer the most basic operational question: is there a problem right now? +Open the dashboard and look at the Summary row. Six stat panels at the top answer the first question: is the cluster intact? -Max Latency shows the highest mailbox latency across all selected nodes as a red timeseries. The value represents how long the oldest unprocessed message has been sitting in some process's mailbox. Under normal conditions this stays under 100ms. Values above 1 second mean at least one process is significantly behind -- it is either overloaded, stuck in a long-running callback, or waiting for an external resource. +- **Zombie count should be zero.** Non-zero means processes have terminated abnormally and were not cleaned up. This requires immediate investigation. +- **Node count should match your expectation.** A missing node means it has left the cluster or lost connectivity. +- **Memory used should be within expected bounds.** A sharp increase since the last check suggests a leak or a load spike. -Stressed Processes shows a stacked area chart with two layers. The light-blue area represents processes with latency under 1ms -- these are technically non-empty mailboxes but the delay is negligible and considered normal operation. The orange area represents processes with latency of 1ms or above -- these are the ones worth investigating. In a healthy system the orange area should be absent or thin. A growing orange area indicates that more and more processes are falling behind. +If the Summary looks normal and you have latency enabled, glance at the Latency row directly below. If Max Latency is under 100ms and the Stressed Processes panel is mostly empty or light-blue -- the system is healthy. Routine check complete. -If both panels look calm -- Max Latency under 100ms, no orange in Stressed Processes -- the system is healthy. No further investigation needed. +If you are not using `-tags=latency`, expand the Mailbox Depth row instead. Max Depth per Node is the closest equivalent to Max Latency as a backpressure signal. If all nodes show zero or low depth, the system is healthy. For a deeper routine check, expand the Process Activity row and glance at Message Throughput -- a sudden drop compared to the previous period may indicate stalled processes even when depth looks normal. -#### React to these signals +#### Something is wrong: start with latency -**Max Latency spikes above 1 second.** At least one process is severely behind. This is the strongest signal that something is wrong. Scroll down to the Top Stressed Processes table to identify the specific process by its application, behavior, name, and PID. +When a problem is detected -- alerts fire, users report slowness, or the Summary shows unusual values -- the latency panels are the first place to investigate. They answer "are my actors keeping up with their workload?" -**Orange area growing in Stressed Processes.** Multiple processes are accumulating latency. This is broader than a single stuck process -- it suggests the node or cluster is under general pressure. Look at the Latency Distribution panel to understand how the latency is spread across ranges. Check the CPU panels to see if the system is compute-bound. +If you are not using `-tags=latency`, skip to the Mailbox Depth row. Rising depth on a node means processes are receiving messages faster than they can handle them. Use the Depth Distribution panel to assess severity and the Top Processes by Depth table to identify the specific actors. Then continue with the "Understand severity" and "Correlate across panels" sections below -- they apply regardless of whether latency is enabled. -**A spike in Max Latency followed by a quick return to normal.** A temporary burst of load that the system recovered from. Compare the timing with the Process Spawn Rate panel (in the collapsed Processes row) to see if the spike correlates with a batch of new processes starting up or a restart event. +The **Max Latency** panel shows the highest mailbox latency across all selected nodes as a red timeseries. Under normal conditions this stays under 100ms. Values above 1 second mean at least one process is significantly behind -- it is either overloaded, stuck in a long-running callback, or waiting for an external resource. -**Max Latency persistently elevated (minutes, not seconds).** A process is stuck. It has a message in its mailbox that arrived long ago and has not been processed. This is different from overload -- overload causes latency to fluctuate with traffic, while a stuck process shows a steadily increasing or flat high value. Identify the process in the Top Stressed Processes table and investigate its behavior. +The **Stressed Processes** panel shows a stacked area chart with two layers. Light-blue represents processes with latency under 1ms (negligible, normal operation). Orange represents processes with latency of 1ms or above (worth investigating). A growing orange area means more processes are falling behind over time. -#### Identify the node +Read these two panels together: -The middle tier contains **Max Latency per Node** (left) and **Stressed Processes per Node** (right). These panels break down the cluster-wide values into individual nodes. +- **Max Latency spikes above 1 second** -- at least one process is severely behind. Scroll down to the Top Stressed Processes table to identify it by application, behavior, name, and PID. +- **Orange area growing in Stressed Processes** -- multiple processes are accumulating latency. The problem is broader than a single actor. Check the Latency Distribution to understand severity, and the CPU panels to see if the system is compute-bound. +- **Max Latency spike followed by quick return to normal** -- a temporary burst. Compare timing with Process Spawn Rate in the Processes row to check for lifecycle event correlation. +- **Max Latency persistently elevated (minutes, not seconds)** -- a stuck process. Unlike overload (which fluctuates with traffic), a stuck process shows a steadily increasing or flat high value. Find it in the Top Stressed Processes table. -If one node shows high latency while others are calm, the problem is localized. That specific node may be overloaded, running a stuck process, or experiencing resource constraints. Cross-reference with the CPU, Memory, and Network panels for that node. +#### Narrow down: node or cluster? -If multiple nodes show similar latency patterns, the problem is systemic. Common causes include a shared external dependency that is slow, a distributed traffic pattern that overwhelms multiple nodes simultaneously, or a deployment issue affecting the entire cluster. +The **Max Latency per Node** and **Stressed Processes per Node** panels break the cluster-wide picture into individual nodes. -The relationship between per-node max latency and per-node stressed count is informative. A node with high max latency but low stressed count has one problematic process while the rest are fine. A node with moderate latency but high stressed count is generally overloaded -- many processes are all slightly behind. +If one node stands out while others are calm, the problem is localized. Cross-reference with CPU, Memory, and Network panels for that node. A node with high max latency but low stressed count has one problematic process. A node with moderate latency but high stressed count is generally overloaded. -#### Understand the distribution +If multiple nodes show similar patterns, the problem is systemic -- a shared external dependency, a cluster-wide traffic pattern, or a deployment issue. -The **Latency Distribution** panel shows a stacked area chart where each layer represents a latency range. The color gradient runs from green (1ms, 5ms, 10ms) through yellow (50ms, 100ms) to orange (500ms, 1s) and red/dark-red (5s, 10s, 30s, 60s, 60s+). The legend is sorted from highest to lowest range. +#### Understand severity: the distribution panels -In a healthy system, the chart is predominantly green or empty. Processes with latency under 10ms are operating normally -- the delay is within typical scheduling jitter. +The **Latency Distribution** panel shows a stacked area chart where each layer represents a latency range. Colors run from green (1ms-10ms, normal) through yellow (50ms-100ms, elevated) to orange (500ms-1s, concerning) and red (5s-60s+, critical). The legend is sorted from highest to lowest range. -Yellow layers (50ms-100ms) appearing during traffic spikes are acceptable if they disappear when the spike ends. Persistent yellow suggests the system is running near capacity. +This panel distinguishes two scenarios that look similar in Max Latency: one stuck process (a single red sliver at the top of an otherwise green chart) versus widespread degradation (the entire chart shifting from green toward orange). The first requires investigating a specific process. The second requires scaling or load shedding. -Orange and red layers indicate processes that are seriously behind. Even a thin red sliver means some process has latency measured in seconds. Look at the Top Stressed Processes table to find it. +The **Depth Distribution** panel (expand the Mailbox Depth row) provides a complementary view. Where latency distribution shows how long messages wait, depth distribution shows how many messages are queued. The color gradient follows the same flame convention: green for 1-10 messages, yellow for 50-100, red for 5K-10K+. A process with high depth but low latency processes messages quickly but receives many at once. A process with low depth but high latency is slow but not overwhelmed. -The distribution panel is particularly useful for distinguishing between two scenarios that look similar in the Max Latency panel: one stuck process (a single red sliver while the rest is green) versus widespread degradation (the entire chart shifting from green toward orange). The former requires investigating a specific process; the latter requires scaling or load-shedding. +The **Utilization Distribution** panel (expand the Process Activity row) shows the fraction of lifetime each process spends inside callbacks. Most processes should be in the low ranges (1%-10%). A shift toward higher ranges (50%+) across many processes means the cluster is running compute-heavy workloads and may need scaling. #### Find the specific process -The **Top Stressed Processes** table at the bottom lists up to 50 processes with the highest mailbox latency across the cluster. Columns include Application, Behavior, Name, PID, Node, and Latency (plus Kubernetes labels when running in a containerized environment). The table is sorted by latency in descending order. - -This table directly answers "which process is the bottleneck?" The Application and Behavior columns tell you what kind of actor it is. The Name column gives its registered name if it has one. The Node column tells you where it runs. - -Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme latency (minutes) while others are in milliseconds points to a stuck or blocked process that needs specific investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques to identify what a stuck process is doing. - -#### Correlate with other panels +Each metric group has a top-N table at the bottom of its row: -Latency data becomes most useful when combined with other dashboard panels: +- **Top Stressed Processes** (Latency row) -- processes with the highest mailbox latency. Answers "which process is the bottleneck?" +- **Top Processes by Depth** (Mailbox Depth row) -- processes with the deepest queues. Answers "which process has the most messages waiting?" +- **Top Processes by Utilization** (Process Activity row) -- processes that spend the most time in callbacks. Answers "which process is doing the most work?" -- **High latency + high CPU** -- processes are compute-bound. The actors are doing heavy work in their callbacks and cannot keep up with the message rate. Consider distributing work across more processes or offloading expensive computation. +All tables show Application, Behavior, Name, PID, Node, and the metric value (plus Kubernetes labels when available). Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme values points to a specific process that needs investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques. -- **High latency + low CPU** -- processes are blocked on something other than computation. Common causes: waiting for external I/O (database, HTTP calls), waiting for responses from other actors via synchronous calls, or contention on shared resources. +#### Correlate across panels -- **High latency + growing memory** -- mailboxes are accumulating messages faster than processes can handle them. The unprocessed messages consume memory. If this continues, the node will eventually run out of memory. +Individual metrics become most powerful when combined: -- **High latency + network traffic spike** -- a burst of remote messages is overwhelming the receiving processes. Check the Network per Node and Network Detail panels to identify which node-to-node link is responsible. +- **High latency + high depth** -- the process is both slow and receiving more messages than it can handle. The mailbox is growing. This is the clearest sign of overload. +- **High latency + low depth** -- a single message is being processed slowly (long-running callback) or the process is blocked waiting for something. The mailbox is not growing because new messages are not arriving. +- **High depth + low latency** -- the process receives bursts but processes them quickly. The depth spikes are transient. Usually not a problem unless the bursts grow over time. +- **High latency + high CPU** -- processes are compute-bound. Actors are doing heavy work in callbacks and cannot keep up with the message rate. Consider distributing work across more processes or offloading expensive computation. +- **High latency + low CPU** -- processes are blocked on something other than computation. Common causes: waiting for external I/O, waiting for responses from other actors via synchronous calls, or contention on shared resources. +- **High latency + growing memory** -- mailboxes are accumulating messages faster than processes can handle them. The unprocessed messages consume memory. If this continues, the node will run out of memory. +- **High latency + network traffic spike** -- a burst of remote messages is overwhelming the receiving processes. Check Network per Node and Network Detail panels to identify the responsible link. +- **Running time per node approaching CPU core count** -- the node is compute-saturated. All available CPU time is spent inside actor callbacks. Either reduce the workload or add capacity. +- **Message throughput drop with stable process count** -- processes are alive but not doing work. They may be blocked on external calls or waiting for messages that are no longer arriving (upstream failure). ## Observer Integration @@ -459,4 +536,4 @@ func (m *AppMetrics) HandleInspect(from gen.PID, item ...string) map[string]stri } ``` -For detailed configuration options, see the `metrics.Options` struct and `ActorBehavior` interface in the package. For examples of custom metrics, see the [example directory](https://github.com/ergo-services/actor/tree/main/metrics/example). +For detailed configuration options, see the `metrics.Options` struct and `ActorBehavior` interface in the package. For examples of custom metrics, see the [metrics actor repository](https://github.com/ergo-services/actor). From 4cdbe5e6ddab2286edfb0cf98f6ad5449c3af6d0 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Sat, 21 Feb 2026 13:41:09 +0100 Subject: [PATCH 013/122] sync --- docs/advanced/debugging.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/advanced/debugging.md b/docs/advanced/debugging.md index 6ff16ba69..d4b578167 100644 --- a/docs/advanced/debugging.md +++ b/docs/advanced/debugging.md @@ -387,3 +387,4 @@ Debugging actor systems requires tools that bridge the gap between logical actor - **Observer integration** for visual inspection of running systems Combined with Go's standard profiling tools, these capabilities enable effective debugging of even complex distributed systems. + From 97534a112a0061be34c62da74abacf5400d53ce8 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Sat, 21 Feb 2026 14:04:49 +0100 Subject: [PATCH 014/122] update docs for actors/metrics --- docs/extra-library/actors/metrics.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 119b88551..90147f5f5 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -420,19 +420,15 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Mailbox Latency** (expanded, requires `-tags=latency`) - Six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". -**Mailbox Depth** (collapsed) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." +**Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." **Process Activity** (collapsed) - Four panels covering utilization and throughput. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Message Throughput per Node shows `rate(messages_in)` and `rate(messages_out)` per node in messages per second. Top Processes by Utilization is a table showing the busiest actors by lifetime utilization. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization. When this value approaches the available CPU core count, the node is compute-saturated. **Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. -**CPU** - User and system CPU time normalized by core count, displayed as percentages. High user CPU means compute-bound workload. High system CPU relative to user suggests excessive I/O or syscalls rather than application work. +**Resources** (collapsed) - Four panels covering CPU and memory. CPU User Time and CPU System Time are normalized by core count and displayed as percentages. High user CPU means compute-bound workload; high system CPU relative to user suggests excessive I/O or syscalls. Memory (OS:used) and Memory (Runtime:alloc) show memory usage over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. -**Memory** - OS-reported memory and Go runtime allocation over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. - -**Network** - Four panels covering cluster totals and per-node breakdowns for message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. - -**Network Detail** - Message and byte rates between specific node pairs. Useful for tracing inter-node communication paths and identifying saturated links. +**Network** (collapsed) - Six panels covering cluster totals, per-node breakdowns, and node-pair detail for both message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. **Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). @@ -450,7 +446,7 @@ Open the dashboard and look at the Summary row. Six stat panels at the top answe If the Summary looks normal and you have latency enabled, glance at the Latency row directly below. If Max Latency is under 100ms and the Stressed Processes panel is mostly empty or light-blue -- the system is healthy. Routine check complete. -If you are not using `-tags=latency`, expand the Mailbox Depth row instead. Max Depth per Node is the closest equivalent to Max Latency as a backpressure signal. If all nodes show zero or low depth, the system is healthy. For a deeper routine check, expand the Process Activity row and glance at Message Throughput -- a sudden drop compared to the previous period may indicate stalled processes even when depth looks normal. +If you are not using `-tags=latency`, check the Mailbox Depth row below. Max Depth per Node is the closest equivalent to Max Latency as a backpressure signal. If all nodes show zero or low depth, the system is healthy. For a deeper routine check, expand the Process Activity row and glance at Message Throughput -- a sudden drop compared to the previous period may indicate stalled processes even when depth looks normal. #### Something is wrong: start with latency @@ -473,7 +469,7 @@ Read these two panels together: The **Max Latency per Node** and **Stressed Processes per Node** panels break the cluster-wide picture into individual nodes. -If one node stands out while others are calm, the problem is localized. Cross-reference with CPU, Memory, and Network panels for that node. A node with high max latency but low stressed count has one problematic process. A node with moderate latency but high stressed count is generally overloaded. +If one node stands out while others are calm, the problem is localized. Cross-reference with Resources and Network panels for that node. A node with high max latency but low stressed count has one problematic process. A node with moderate latency but high stressed count is generally overloaded. If multiple nodes show similar patterns, the problem is systemic -- a shared external dependency, a cluster-wide traffic pattern, or a deployment issue. @@ -483,7 +479,7 @@ The **Latency Distribution** panel shows a stacked area chart where each layer r This panel distinguishes two scenarios that look similar in Max Latency: one stuck process (a single red sliver at the top of an otherwise green chart) versus widespread degradation (the entire chart shifting from green toward orange). The first requires investigating a specific process. The second requires scaling or load shedding. -The **Depth Distribution** panel (expand the Mailbox Depth row) provides a complementary view. Where latency distribution shows how long messages wait, depth distribution shows how many messages are queued. The color gradient follows the same flame convention: green for 1-10 messages, yellow for 50-100, red for 5K-10K+. A process with high depth but low latency processes messages quickly but receives many at once. A process with low depth but high latency is slow but not overwhelmed. +The **Depth Distribution** panel (in the Mailbox Depth row) provides a complementary view. Where latency distribution shows how long messages wait, depth distribution shows how many messages are queued. The color gradient follows the same flame convention: green for 1-10 messages, yellow for 50-100, red for 5K-10K+. A process with high depth but low latency processes messages quickly but receives many at once. A process with low depth but high latency is slow but not overwhelmed. The **Utilization Distribution** panel (expand the Process Activity row) shows the fraction of lifetime each process spends inside callbacks. Most processes should be in the low ranges (1%-10%). A shift toward higher ranges (50%+) across many processes means the cluster is running compute-heavy workloads and may need scaling. From b26b7950c7f5ab731c61455021e498dcaf414ba4 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 23 Feb 2026 17:33:52 +0100 Subject: [PATCH 015/122] events. infos. all around them --- CHANGELOG.md | 1 + README.md | 2 + docs/basics/events.md | 30 ++++++++++++++ docs/basics/node.md | 2 +- docs/extra-library/actors/metrics.md | 52 +++++++++++++++++------- gen/node.go | 21 ++++++++++ gen/target.go | 18 ++++++--- node/node.go | 20 ++++++++++ node/tm/event.go | 59 +++++++++++++++++++++++----- node/tm/manager.go | 11 +++++- node/tm/scenarios_test.go | 4 +- testing/unit/node.go | 8 ++++ 12 files changed, 193 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 442cf8958..aa1f85a40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added **process lifecycle counters** to `gen.NodeInfo` - `ProcessesSpawned`, `ProcessesSpawnFailed`, `ProcessesTerminated` for cumulative statistics * Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and latency fields to `MailboxQueues` in `ProcessInfo`. See [Debugging](https://docs.ergo.services/advanced/debugging) documentation * Added **`Node.ProcessRangeShortInfo`** for efficient callback-based iteration over all processes with their current state. See [Metrics actor](https://docs.ergo.services/extra-library/actors/metrics) for Prometheus integration +* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index 8a72f37d0..ae32474c6 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,8 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and `MailboxQueues` latency fields to `ProcessInfo`. Added `Node.ProcessRangeShortInfo` for efficient iteration over all processes. See [actor/metrics](https://github.com/ergo-services/actor-metrics) for Prometheus integration with histogram, top-N, and Grafana dashboard +* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at diff --git a/docs/basics/events.md b/docs/basics/events.md index b51b89670..69153912a 100644 --- a/docs/basics/events.md +++ b/docs/basics/events.md @@ -104,6 +104,36 @@ Each `gen.MessageEvent` contains: Subscribers receive these wrapped messages and extract the application data. The wrapping provides context: which event this came from, when it was published, allowing subscribers to handle events from multiple sources or correlate timing. +## Event Statistics + +Each registered event tracks per-event counters: how many messages were published, how many were delivered to local subscribers, and how many were sent to remote nodes. These counters are available through `Node.EventInfo` and `Node.EventRangeInfo`. + +To query a specific event: + +```go +info, err := node.EventInfo(gen.Event{Name: "price_update", Node: "node@host"}) +// info.MessagesPublished - total messages published to this event +// info.MessagesLocalSent - messages delivered to local subscribers +// info.MessagesRemoteSent - messages sent to remote subscriber nodes +// info.Subscribers - current subscriber count +``` + +To iterate over all registered events on the node: + +```go +node.EventRangeInfo(func(info gen.EventInfo) bool { + fmt.Printf("event %s: published %d, local %d, remote %d\n", + info.Event.Name, + info.MessagesPublished, + info.MessagesLocalSent, + info.MessagesRemoteSent, + ) + return true // continue iteration +}) +``` + +Node-level aggregate counters are also available in `gen.NodeInfo` via `node.Info()`: `EventsPublished`, `EventsLocalSent`, and `EventsRemoteSent` sum across all events on the node. + ## Practical Patterns Events fit several common scenarios. diff --git a/docs/basics/node.md b/docs/basics/node.md index 59952d52b..1dccd24fa 100644 --- a/docs/basics/node.md +++ b/docs/basics/node.md @@ -16,7 +16,7 @@ When you start a node, you're launching a complete system with several subsystem **Network Stack** - The node handles all network communication. It discovers other nodes, establishes connections, encodes messages, and manages the complexity of distributed communication. This is what makes network transparency possible. -**Pub/Sub System** - Links, monitors, and events all work through a publisher/subscriber mechanism in the node core. When a process terminates or an event fires, the node knows who's subscribed and delivers the notifications. +**Pub/Sub System** - Links, monitors, and events all work through a publisher/subscriber mechanism in the node core. When a process terminates or an event fires, the node knows who's subscribed and delivers the notifications. The node provides `EventInfo` to query statistics for a specific event and `EventRangeInfo` for callback-based iteration over all registered events with their per-event counters (messages published, local/remote deliveries). **Logging** - Every log message goes through the node, which fans it out to registered loggers. This centralized logging makes it easy to capture, filter, and route log output. diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 90147f5f5..636779162 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -20,6 +20,8 @@ The metrics actor addresses this by tracking: **Network metrics** - For distributed Ergo clusters, tracking bytes and messages flowing between nodes reveals network bottlenecks, routing inefficiencies, or failing connections. +**Event metrics** - For pub/sub events, tracking which events have the most subscribers, which generate the most delivery load, and which are wasteful (publishing into the void or registered but unused). These reveal whether your event-driven architecture is efficient or accumulating overhead. See [Events](../../basics/events.md) for the pub/sub model and [Pub/Sub Internals](../../advanced/pub-sub-internals.md) for the shared subscription optimization that affects how delivery counters work. + **Application metrics** - How many applications are loaded and running. Applications failing to start or terminating unexpectedly appear in these counts. These base metrics provide system-level visibility. For application-specific metrics (request rates, business transactions, custom counters), you extend the metrics actor with your own Prometheus collectors. @@ -58,7 +60,7 @@ When you spawn the metrics actor: 1. **HTTP endpoint starts** at the configured host and port. The `/metrics` endpoint immediately serves Prometheus-formatted data. -2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), and per-process metrics (mailbox depth, utilization, latency, aggregates) update at the configured interval. +2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), per-process metrics (mailbox depth, utilization, latency, aggregates), and per-event metrics (subscriber distribution, delivery rates, waste patterns) update at the configured interval. 3. **Custom metrics update** via `CollectMetrics()` callback or `HandleMessage()` processing, depending on your implementation. @@ -108,7 +110,7 @@ options := metrics.Options{ Host: "0.0.0.0", // Listen on all interfaces Port: 9090, // Prometheus default port CollectInterval: 5 * time.Second, // Collect every 5 seconds - TopN: 50, // Top-N processes for each metric group + TopN: 50, // Top-N entries for each metric group (processes and events) } node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) @@ -118,7 +120,7 @@ node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) **Port** should not conflict with other services. Prometheus conventionally uses `9090`, but many Ergo applications use that for other purposes. Choose a port that doesn't collide with your application's HTTP servers, Observer UI (default `9911`), or other metrics exporters. -**TopN** sets how many top processes are tracked for each per-process metric group -- mailbox depth, utilization, and latency (default: 50). Higher values provide more visibility but increase Prometheus cardinality. Set to 0 is not supported; the minimum effective value is 1. +**TopN** sets how many top entries are tracked for each metric group -- mailbox depth, utilization, latency for processes, and subscribers, published, local sent, remote sent for events (default: 50). Higher values provide more visibility but increase Prometheus cardinality. Set to 0 is not supported; the minimum effective value is 1. **CollectInterval** controls how frequently the actor queries node statistics. Shorter intervals provide more granular time-series data but increase CPU usage for collection. Longer intervals reduce overhead but miss short-lived spikes. For most applications, 10-15 seconds balances responsiveness with resource usage. Prometheus typically scrapes every 15-60 seconds, so collecting more frequently than your scrape interval wastes resources. @@ -146,7 +148,10 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_applications_running` | Gauge | Applications currently active. Compare to total to identify stopped or failed applications. | | `ergo_registered_names_total` | Gauge | Processes registered with atom names. High counts suggest heavy use of named processes for routing. | | `ergo_registered_aliases_total` | Gauge | Total number of registered aliases. Includes aliases created by processes via `CreateAlias()` and aliases identifying meta-processes. | -| `ergo_registered_events_total` | Gauge | Event subscriptions active in the node. High counts indicate extensive pub/sub usage. | +| `ergo_registered_events_total` | Gauge | Total number of registered events on this node. | +| `ergo_events_published_total` | Gauge | Cumulative number of events published on this node. Includes both local producer publishes and events arriving from remote nodes. Use `rate()` to get publish throughput. | +| `ergo_events_local_sent_total` | Gauge | Cumulative number of event messages delivered to local subscribers. This reflects the actual fanout load -- a single publish with 100 subscribers produces 100 local deliveries. | +| `ergo_events_remote_sent_total` | Gauge | Cumulative number of event messages sent to remote nodes. Due to shared subscription optimization, one message is sent per remote node regardless of how many subscribers that node has. See [Pub/Sub Internals](../../advanced/pub-sub-internals.md). | ### Network Metrics @@ -226,22 +231,37 @@ These are cumulative values -- apply `rate()` in Prometheus to get per-second ra `rate(ergo_process_messages_in)` and `rate(ergo_process_messages_out)` give the node-level message throughput in messages per second. `rate(ergo_process_running_time_seconds)` gives the node-level actor CPU utilization in seconds of callback execution per second -- when this value approaches the number of available CPU cores, the node is compute-saturated. -### Per-Process Metrics Collection +### Event Metrics + +The metrics actor collects per-event pub/sub metrics using `Node.EventRangeInfo()`, which iterates over all registered events and returns their current statistics. This provides visibility into the pub/sub layer: which events have the most subscribers, which generate the most delivery load, and which are wasteful. The subscriber count for each event includes both `LinkEvent` and `MonitorEvent` subscribers. -All per-process metrics (latency, depth, utilization, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, and utilization collectors simultaneously. Top-N selection uses a min-heap for O(N) efficiency. This design ensures that adding more metric types does not multiply the number of iterations over the process table. +No build tags required. Event metrics are always active. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_event_subscribers_distribution` | Gauge | `range` | Number of events in each subscriber count range. Snapshot per collect cycle. | +| `ergo_event_subscribers_max` | Gauge | - | Maximum subscriber count across all events on this node. | +| `ergo_event_waste` | Gauge | `reason` | Number of events with wasteful usage patterns. Snapshot per collect cycle. | +| `ergo_event_subscribers_top` | Gauge | `event`, `producer` | Top-N events by subscriber count. | +| `ergo_event_published_top` | Gauge | `event`, `producer` | Top-N events by messages published. | +| `ergo_event_local_sent_top` | Gauge | `event`, `producer` | Top-N events by messages delivered to local subscribers. | +| `ergo_event_remote_sent_top` | Gauge | `event`, `producer` | Top-N events by messages sent to remote nodes. | -### Cardinality +Subscriber distribution ranges: 0, 1, 2-5, 6-10, 11-50, 51-100, 101-500, 501-1K, 1K+. Each range represents an upper boundary. The "1K+" range counts events with more than 1000 subscribers. -For a cluster of 500 nodes with `TopN=50`: +The waste metric classifies events into three patterns: -- Depth distribution + max + top-N: 500 x (10 + 1 + 50) = 30,500 -- Utilization distribution + max + top-N: 500 x (8 + 1 + 50) = 29,500 -- Aggregates: 500 x 3 = 1,500 -- Latency distribution + max + count + top-N: 500 x (12 + 2 + 50) = 32,000 (with `-tags=latency`) -- Total without latency: ~61,500 series -- Total with latency: ~93,500 series +- **`idle`** -- registered but has zero subscribers and zero publishes. A forgotten event consuming resources. +- **`no_subscribers`** -- actively publishing but nobody is subscribed. The producer is doing work (serialization, message construction) for nothing. This often means the producer is not using the `Notify` option to detect when subscribers appear and disappear. See [Events](../../basics/events.md) for the `Notify` mechanism. +- **`no_publishing`** -- has subscribers waiting but the producer has never published. Could be normal for lazy producers that start publishing on demand, or could indicate a bug where the producer is publishing to the wrong event name. -For a typical cluster of 30 nodes, the total is approximately 6,000 series (or 10,000 with latency). At a 15-second Prometheus scrape interval and default 15-day retention, this amounts to roughly 1.3 GB of disk space -- negligible for any modern monitoring setup. +Events that have both subscribers and publishes are considered healthy and are not counted in any waste category. + +The distinction between `published`, `local_sent`, and `remote_sent` in the top-N metrics reflects the pub/sub delivery model. A single publish fans out to all local subscribers (so `local_sent` can be much larger than `published`) and sends one message per remote subscriber node (due to the [shared subscription optimization](../../advanced/pub-sub-internals.md)). Comparing these values reveals the actual delivery cost of each event. + +### Per-Process Metrics Collection + +All per-process metrics (latency, depth, utilization, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, and utilization collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. ## Custom Metrics @@ -422,6 +442,8 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." +**Events** (collapsed) - Nine panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Waste is a stacked timeseries showing events with wasteful patterns: idle (registered but unused), no subscribers (publishing into the void), and no publishing (subscribers waiting). Registered Events per Node and Max Subscribers per Node provide per-node breakdown. Subscriber Distribution is a full-width stacked chart showing how events are distributed by subscriber count (0 to 1K+). Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. + **Process Activity** (collapsed) - Four panels covering utilization and throughput. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Message Throughput per Node shows `rate(messages_in)` and `rate(messages_out)` per node in messages per second. Top Processes by Utilization is a table showing the busiest actors by lifetime utilization. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization. When this value approaches the available CPU core count, the node is compute-saturated. **Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. diff --git a/gen/node.go b/gen/node.go index 078a5e97d..1f094598f 100644 --- a/gen/node.go +++ b/gen/node.go @@ -305,6 +305,18 @@ type Node interface { // Returns ErrNodeTerminated in other states, ErrEventUnknown if not found. UnregisterEvent(name Atom) error + // EventInfo returns information about the given event. + // Available in: Running state only. + // Returns ErrNodeTerminated in other states, ErrEventUnknown if not found. + EventInfo(event Event) (EventInfo, error) + + // EventRangeInfo iterates over all registered events calling fn for each. + // The callback receives EventInfo and returns true to continue + // or false to stop iteration. + // Available in: Running state only. + // Returns ErrNodeTerminated in other states. + EventRangeInfo(fn func(EventInfo) bool) error + // SendExit sends a graceful termination request to the process. // Sender is the node's core PID. // Available in: Running state only. @@ -751,6 +763,15 @@ type NodeInfo struct { // RegisteredEvents is the total number of registered events. RegisteredEvents int64 + // EventsPublished is the cumulative number of events published. + EventsPublished int64 + + // EventsLocalSent is the cumulative number of event messages sent to local subscribers. + EventsLocalSent int64 + + // EventsRemoteSent is the cumulative number of event messages sent to remote subscribers. + EventsRemoteSent int64 + // ApplicationsTotal is the total number of loaded applications. ApplicationsTotal int64 diff --git a/gen/target.go b/gen/target.go index 4c4a660be..f854194c5 100644 --- a/gen/target.go +++ b/gen/target.go @@ -33,6 +33,7 @@ type TargetManager interface { UnregisterEvent(producer PID, name Atom) error PublishEvent(from PID, token Ref, options MessageOptions, message MessageEvent) error EventInfo(event Event) (EventInfo, error) + EventRangeInfo(fn func(EventInfo) bool) error LinksFor(consumer PID) []any MonitorsFor(consumer PID) []any @@ -53,11 +54,15 @@ type TargetManager interface { // EventInfo contains event metadata and statistics type EventInfo struct { - Producer PID - BufferSize int - CurrentBuffer int - Notify bool - Subscribers int64 + Event Event + Producer PID + BufferSize int + CurrentBuffer int + Notify bool + Subscribers int64 + MessagesPublished int64 + MessagesLocalSent int64 + MessagesRemoteSent int64 } type TargetManagerInfo struct { @@ -71,5 +76,6 @@ type TargetManagerInfo struct { DownMessagesProduced int64 // Total down messages generated DownMessagesDelivered int64 // Total down messages delivered EventsPublished int64 // Total events published - EventsSent int64 // Total event messages sent to subscribers + EventsLocalSent int64 // Total event messages sent to local subscribers + EventsRemoteSent int64 // Total event messages sent to remote subscribers } diff --git a/node/node.go b/node/node.go index 81de1a19a..68eb3e1c5 100644 --- a/node/node.go +++ b/node/node.go @@ -717,6 +717,12 @@ func (n *node) Info() (gen.NodeInfo, error) { return true }) + tmInfo := n.targets.Info() + info.RegisteredEvents = tmInfo.Events + info.EventsPublished = tmInfo.EventsPublished + info.EventsLocalSent = tmInfo.EventsLocalSent + info.EventsRemoteSent = tmInfo.EventsRemoteSent + info.ApplicationsTotal = int64(len(n.Applications())) info.ApplicationsRunning = int64(len(n.ApplicationsRunning())) @@ -1072,6 +1078,20 @@ func (n *node) UnregisterEvent(name gen.Atom) error { return n.unregisterEvent(name, n.corePID) } +func (n *node) EventInfo(event gen.Event) (gen.EventInfo, error) { + if n.isRunning() == false { + return gen.EventInfo{}, gen.ErrNodeTerminated + } + return n.targets.EventInfo(event) +} + +func (n *node) EventRangeInfo(fn func(gen.EventInfo) bool) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + return n.targets.EventRangeInfo(fn) +} + func (n *node) SendExit(pid gen.PID, reason error) error { if n.isRunning() == false { return gen.ErrNodeTerminated diff --git a/node/tm/event.go b/node/tm/event.go index 5eefdb222..e60709f82 100644 --- a/node/tm/event.go +++ b/node/tm/event.go @@ -198,12 +198,15 @@ func (tm *targetManager) publishEventLocalProducer( } } + // Increment per-event published counter under lock + entry.messagesPublished.Add(1) + // Copy slices under lock (minimize lock hold time) linkSubs := entry.linkSubscribers monitorSubs := entry.monitorSubscribers tm.mutex.Unlock() - // Increment published counter + // Increment global published counter tm.eventsPublished.Add(1) // Collect local consumers and remote nodes (no lock needed) @@ -231,7 +234,9 @@ func (tm *targetManager) publishEventLocalProducer( // Send to local consumers directly if len(localConsumers) > 0 { tm.core.RouteSendEventMessages(from, localConsumers, options, message) - tm.eventsSent.Add(int64(len(localConsumers))) + n := int64(len(localConsumers)) + entry.messagesLocalSent.Add(n) + tm.eventsLocalSent.Add(n) } // Send to remote nodes @@ -241,7 +246,8 @@ func (tm *targetManager) publishEventLocalProducer( continue } connection.SendEvent(from, options, message) - tm.eventsSent.Add(1) + entry.messagesRemoteSent.Add(1) + tm.eventsRemoteSent.Add(1) } return nil @@ -272,7 +278,7 @@ func (tm *targetManager) publishEventRemoteProducer( if len(localConsumers) > 0 { tm.core.RouteSendEventMessages(from, localConsumers, options, message) - tm.eventsSent.Add(int64(len(localConsumers))) + tm.eventsLocalSent.Add(int64(len(localConsumers))) } return nil @@ -754,16 +760,51 @@ func (tm *targetManager) EventInfo(event gen.Event) (gen.EventInfo, error) { // Build event info info := gen.EventInfo{ - Producer: entry.producer, - BufferSize: entry.bufferSize, - CurrentBuffer: len(entry.buffer), - Notify: entry.notify, - Subscribers: entry.subscriberCount, + Event: event, + Producer: entry.producer, + BufferSize: entry.bufferSize, + CurrentBuffer: len(entry.buffer), + Notify: entry.notify, + Subscribers: entry.subscriberCount, + MessagesPublished: entry.messagesPublished.Load(), + MessagesLocalSent: entry.messagesLocalSent.Load(), + MessagesRemoteSent: entry.messagesRemoteSent.Load(), } return info, nil } +func (tm *targetManager) EventRangeInfo(fn func(gen.EventInfo) bool) error { + tm.mutex.RLock() + + // Snapshot event infos under lock + infos := make([]gen.EventInfo, 0, len(tm.events)) + for event, entry := range tm.events { + info := gen.EventInfo{ + Event: event, + Producer: entry.producer, + BufferSize: entry.bufferSize, + CurrentBuffer: len(entry.buffer), + Notify: entry.notify, + Subscribers: entry.subscriberCount, + MessagesPublished: entry.messagesPublished.Load(), + MessagesLocalSent: entry.messagesLocalSent.Load(), + MessagesRemoteSent: entry.messagesRemoteSent.Load(), + } + infos = append(infos, info) + } + tm.mutex.RUnlock() + + // Iterate without lock + for _, info := range infos { + if fn(info) == false { + break + } + } + + return nil +} + // Helper: get event buffer func (tm *targetManager) getEventBuffer(entry *eventEntry) []gen.MessageEvent { if entry.buffer == nil { diff --git a/node/tm/manager.go b/node/tm/manager.go index c98d3628e..b112e9b0f 100644 --- a/node/tm/manager.go +++ b/node/tm/manager.go @@ -28,7 +28,8 @@ type targetManager struct { downMessagesProduced atomic.Int64 downMessagesDelivered atomic.Int64 eventsPublished atomic.Int64 - eventsSent atomic.Int64 + eventsLocalSent atomic.Int64 + eventsRemoteSent atomic.Int64 } type relationKey struct { @@ -59,6 +60,11 @@ type eventEntry struct { monitorSubscribersIndex map[gen.PID]int subscriberCount int64 + + // Per-event statistics + messagesPublished atomic.Int64 + messagesLocalSent atomic.Int64 + messagesRemoteSent atomic.Int64 } type Options struct{} @@ -89,6 +95,7 @@ func (tm *targetManager) Info() gen.TargetManagerInfo { DownMessagesProduced: tm.downMessagesProduced.Load(), DownMessagesDelivered: tm.downMessagesDelivered.Load(), EventsPublished: tm.eventsPublished.Load(), - EventsSent: tm.eventsSent.Load(), + EventsLocalSent: tm.eventsLocalSent.Load(), + EventsRemoteSent: tm.eventsRemoteSent.Load(), } } diff --git a/node/tm/scenarios_test.go b/node/tm/scenarios_test.go index c1723beb0..8d42898f5 100644 --- a/node/tm/scenarios_test.go +++ b/node/tm/scenarios_test.go @@ -2622,8 +2622,8 @@ func TestStress_Event_ConcurrentOperations(t *testing.T) { // eventsSent should be 100 * number_of_subscribers_at_publish_time // (varies based on timing, but should be > 0) - if info.EventsSent == 0 { - t.Error("EventsSent should be > 0") + if info.EventsLocalSent == 0 { + t.Error("EventsLocalSent should be > 0") } } diff --git a/testing/unit/node.go b/testing/unit/node.go index 335aee78d..96c3c77df 100644 --- a/testing/unit/node.go +++ b/testing/unit/node.go @@ -609,6 +609,14 @@ func (tn *TestNode) UnregisterEvent(name gen.Atom) error { return nil } +func (tn *TestNode) EventInfo(event gen.Event) (gen.EventInfo, error) { + return gen.EventInfo{}, gen.ErrEventUnknown +} + +func (tn *TestNode) EventRangeInfo(fn func(gen.EventInfo) bool) error { + return nil +} + func (tn *TestNode) SendExit(pid gen.PID, reason error) error { // Check for failure injection if err := tn.CheckMethodFailure("SendExit", pid, reason); err != nil { From b4d06d52453bb786b9e8edd659f2eafbbf575762 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 24 Feb 2026 09:14:14 +0100 Subject: [PATCH 016/122] fix message counters --- docs/basics/events.md | 2 ++ docs/extra-library/actors/metrics.md | 46 +++++++++++++++------------- node/core.go | 2 ++ node/meta.go | 4 +++ node/meta_start.go | 1 + node/meta_start_pprof.go | 1 + node/process.go | 4 +++ 7 files changed, 38 insertions(+), 22 deletions(-) diff --git a/docs/basics/events.md b/docs/basics/events.md index 69153912a..392aef5ff 100644 --- a/docs/basics/events.md +++ b/docs/basics/events.md @@ -134,6 +134,8 @@ node.EventRangeInfo(func(info gen.EventInfo) bool { Node-level aggregate counters are also available in `gen.NodeInfo` via `node.Info()`: `EventsPublished`, `EventsLocalSent`, and `EventsRemoteSent` sum across all events on the node. +The [Metrics actor](../extra-library/actors/metrics.md) automatically exports these counters as Prometheus metrics, along with per-event top-N breakdowns by subscribers, published, local deliveries, and remote sent. It also tracks event utilization state -- whether events are actively used, waiting on demand, or idle. + ## Practical Patterns Events fit several common scenarios. diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 636779162..4b6b5ce86 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -217,17 +217,19 @@ No build tags required. Utilization metrics are always active. Distribution ranges: 1%, 5%, 10%, 25%, 50%, 75%, 90%, 90%+. Processes with zero running time or zero uptime are excluded. Utilization is capped at 1.0 (100%). -### Process Aggregate Metrics +### Process Throughput Metrics -The metrics actor computes node-level aggregate counters by summing per-process values across all processes on the node. These provide a high-level view of how much work the node is doing without the cardinality cost of per-process series. +The metrics actor tracks per-process message throughput (top-N by messages received and sent) and computes node-level aggregate counters by summing per-process values. -| Metric | Type | Description | -|--------|------|-------------| -| `ergo_process_messages_in` | Gauge | Sum of messages received by all processes on this node. | -| `ergo_process_messages_out` | Gauge | Sum of messages sent by all processes on this node. | -| `ergo_process_running_time_seconds` | Gauge | Sum of callback running time across all processes on this node (seconds). | +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_process_messages_in_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by total messages received. Identifies which actors handle the most inbound traffic. | +| `ergo_process_messages_out_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by total messages sent. Identifies which actors generate the most outbound traffic. | +| `ergo_process_messages_in` | Gauge | - | Sum of messages received by all processes on this node. | +| `ergo_process_messages_out` | Gauge | - | Sum of messages sent by all processes on this node. | +| `ergo_process_running_time_seconds` | Gauge | - | Sum of callback running time across all processes on this node (seconds). | -These are cumulative values -- apply `rate()` in Prometheus to get per-second rates. When a process terminates, its contribution is removed from the sum, which may cause the aggregate to decrease momentarily. This is expected and `rate()` handles it correctly in most cases. +Aggregate values are cumulative -- apply `rate()` in Prometheus to get per-second rates. When a process terminates, its contribution is removed from the sum, which may cause the aggregate to decrease momentarily. This is expected and `rate()` handles it correctly in most cases. `rate(ergo_process_messages_in)` and `rate(ergo_process_messages_out)` give the node-level message throughput in messages per second. `rate(ergo_process_running_time_seconds)` gives the node-level actor CPU utilization in seconds of callback execution per second -- when this value approaches the number of available CPU cores, the node is compute-saturated. @@ -239,29 +241,28 @@ No build tags required. Event metrics are always active. | Metric | Type | Labels | Description | |--------|------|--------|-------------| -| `ergo_event_subscribers_distribution` | Gauge | `range` | Number of events in each subscriber count range. Snapshot per collect cycle. | | `ergo_event_subscribers_max` | Gauge | - | Maximum subscriber count across all events on this node. | -| `ergo_event_waste` | Gauge | `reason` | Number of events with wasteful usage patterns. Snapshot per collect cycle. | +| `ergo_event_utilization` | Gauge | `state` | Number of events in each utilization state. Snapshot per collect cycle. | | `ergo_event_subscribers_top` | Gauge | `event`, `producer` | Top-N events by subscriber count. | | `ergo_event_published_top` | Gauge | `event`, `producer` | Top-N events by messages published. | | `ergo_event_local_sent_top` | Gauge | `event`, `producer` | Top-N events by messages delivered to local subscribers. | | `ergo_event_remote_sent_top` | Gauge | `event`, `producer` | Top-N events by messages sent to remote nodes. | -Subscriber distribution ranges: 0, 1, 2-5, 6-10, 11-50, 51-100, 101-500, 501-1K, 1K+. Each range represents an upper boundary. The "1K+" range counts events with more than 1000 subscribers. - -The waste metric classifies events into three patterns: +The utilization metric classifies every registered event into exactly one state: -- **`idle`** -- registered but has zero subscribers and zero publishes. A forgotten event consuming resources. -- **`no_subscribers`** -- actively publishing but nobody is subscribed. The producer is doing work (serialization, message construction) for nothing. This often means the producer is not using the `Notify` option to detect when subscribers appear and disappear. See [Events](../../basics/events.md) for the `Notify` mechanism. -- **`no_publishing`** -- has subscribers waiting but the producer has never published. Could be normal for lazy producers that start publishing on demand, or could indicate a bug where the producer is publishing to the wrong event name. +- **`active`** -- has both published messages and subscribers. The event is doing its job -- producing and delivering messages. +- **`on_demand`** -- the event was registered with `Notify` enabled and is currently waiting (either no subscribers yet, or subscribers present but producer hasn't started). This is the expected state for on-demand producers that use `MessageEventStart`/`MessageEventStop` to control when they publish. See [Events](../../basics/events.md) for the `Notify` mechanism. +- **`idle`** -- registered without `Notify`, has zero subscribers and zero publishes. Likely a forgotten event consuming resources without purpose. +- **`no_subscribers`** -- has published messages but currently no subscribers, registered without `Notify`. The producer is doing work (serialization, message construction) for nothing. +- **`no_publishing`** -- has subscribers waiting but the producer has never published, registered without `Notify`. Could indicate a bug where the producer publishes to the wrong event name, or a producer that hasn't received its data source yet. -Events that have both subscribers and publishes are considered healthy and are not counted in any waste category. +The total across all states equals the total number of registered events on the node. A healthy system shows mostly `active` and `on_demand`. Growth in `idle` or `no_subscribers` over time indicates accumulating waste. The distinction between `published`, `local_sent`, and `remote_sent` in the top-N metrics reflects the pub/sub delivery model. A single publish fans out to all local subscribers (so `local_sent` can be much larger than `published`) and sends one message per remote subscriber node (due to the [shared subscription optimization](../../advanced/pub-sub-internals.md)). Comparing these values reveals the actual delivery cost of each event. ### Per-Process Metrics Collection -All per-process metrics (latency, depth, utilization, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, and utilization collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. +All per-process metrics (latency, depth, utilization, throughput, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. ## Custom Metrics @@ -442,9 +443,9 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." -**Events** (collapsed) - Nine panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Waste is a stacked timeseries showing events with wasteful patterns: idle (registered but unused), no subscribers (publishing into the void), and no publishing (subscribers waiting). Registered Events per Node and Max Subscribers per Node provide per-node breakdown. Subscriber Distribution is a full-width stacked chart showing how events are distributed by subscriber count (0 to 1K+). Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. +**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Registered Events per Node and Max Subscribers per Node provide per-node breakdown. Event Publish Rate per Node and Event Delivery Rate per Node show where producers are most active and where fanout load concentrates. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. -**Process Activity** (collapsed) - Four panels covering utilization and throughput. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Message Throughput per Node shows `rate(messages_in)` and `rate(messages_out)` per node in messages per second. Top Processes by Utilization is a table showing the busiest actors by lifetime utilization. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization. When this value approaches the available CPU core count, the node is compute-saturated. +**Process Activity** (collapsed) - Eight panels organized by topic: message throughput first, then process utilization. Message Throughput (Cluster Total) shows cluster-wide inbound and outbound message rates. Message Throughput per Node breaks this down by node. Top Processes by Inbound Rate and Top Processes by Outbound Rate show which actors currently receive and send the most messages per second -- derived from `rate()` on the per-process cumulative top-N metrics. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Max Utilization per Node shows the busiest process on each node. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization; when this approaches CPU core count, the node is compute-saturated. Top Processes by Utilization table shows the busiest actors by lifetime utilization. **Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. @@ -507,13 +508,14 @@ The **Utilization Distribution** panel (expand the Process Activity row) shows t #### Find the specific process -Each metric group has a top-N table at the bottom of its row: +Each metric group has a top-N panel in its row: - **Top Stressed Processes** (Latency row) -- processes with the highest mailbox latency. Answers "which process is the bottleneck?" - **Top Processes by Depth** (Mailbox Depth row) -- processes with the deepest queues. Answers "which process has the most messages waiting?" +- **Top Processes by Inbound/Outbound Rate** (Process Activity row) -- processes with the highest current message rate. Answers "which process handles the most traffic right now?" - **Top Processes by Utilization** (Process Activity row) -- processes that spend the most time in callbacks. Answers "which process is doing the most work?" -All tables show Application, Behavior, Name, PID, Node, and the metric value (plus Kubernetes labels when available). Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme values points to a specific process that needs investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques. +Process tables show Application, Behavior, Name, PID, Node, and the metric value (plus Kubernetes labels when available). Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme values points to a specific process that needs investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques. #### Correlate across panels diff --git a/node/core.go b/node/core.go index cff0f3d1e..4b8857a51 100644 --- a/node/core.go +++ b/node/core.go @@ -193,6 +193,7 @@ func (n *node) RouteSendAlias(from gen.PID, to gen.Alias, options gen.MessageOpt return gen.ErrMetaMailboxFull } atomic.AddUint64(&m.messagesIn, 1) + atomic.AddUint64(&p.messagesIn, 1) m.handle() return nil } @@ -540,6 +541,7 @@ func (n *node) RouteCallAlias(from gen.PID, to gen.Alias, options gen.MessageOpt return gen.ErrMetaMailboxFull } atomic.AddUint64(&m.messagesIn, 1) + atomic.AddUint64(&p.messagesIn, 1) m.handle() return nil } diff --git a/node/meta.go b/node/meta.go index 3f082b1ad..0285a0a0a 100644 --- a/node/meta.go +++ b/node/meta.go @@ -81,6 +81,7 @@ func (m *meta) SendResponse(to gen.PID, ref gen.Ref, message any) error { return err } atomic.AddUint64(&m.messagesOut, 1) + atomic.AddUint64(&m.p.messagesOut, 1) return nil } @@ -103,6 +104,7 @@ func (m *meta) SendResponseError(to gen.PID, ref gen.Ref, err error) error { return rerr } atomic.AddUint64(&m.messagesOut, 1) + atomic.AddUint64(&m.p.messagesOut, 1) return nil } @@ -187,6 +189,7 @@ func (m *meta) send(to any, message any) error { // so we need to increase messagesIn counter there // and run the process atomic.AddUint64(&m.p.messagesIn, 1) + atomic.AddUint64(&m.p.messagesOut, 1) m.p.run() atomic.AddUint64(&m.messagesOut, 1) @@ -213,6 +216,7 @@ func (m *meta) send(to any, message any) error { } atomic.AddUint64(&m.messagesOut, 1) + atomic.AddUint64(&m.p.messagesOut, 1) return nil } diff --git a/node/meta_start.go b/node/meta_start.go index b21521135..873d924e0 100644 --- a/node/meta_start.go +++ b/node/meta_start.go @@ -146,6 +146,7 @@ func (m *meta) handle() { } m.p.node.RouteSendResponse(m.p.pid, message.From, options, result) atomic.AddUint64(&m.messagesOut, 1) + atomic.AddUint64(&m.p.messagesOut, 1) continue case gen.MailboxMessageTypeExit: diff --git a/node/meta_start_pprof.go b/node/meta_start_pprof.go index 88f92dc5a..27d9fd679 100644 --- a/node/meta_start_pprof.go +++ b/node/meta_start_pprof.go @@ -153,6 +153,7 @@ func (m *meta) handle() { } m.p.node.RouteSendResponse(m.p.pid, message.From, options, result) atomic.AddUint64(&m.messagesOut, 1) + atomic.AddUint64(&m.p.messagesOut, 1) continue case gen.MailboxMessageTypeExit: diff --git a/node/process.go b/node/process.go index 605763257..f2832d4d0 100644 --- a/node/process.go +++ b/node/process.go @@ -620,6 +620,7 @@ func (p *process) SendPID(to gen.PID, message any) error { } atomic.AddUint64(&p.messagesIn, 1) + atomic.AddUint64(&p.messagesOut, 1) p.run() return nil } @@ -944,6 +945,7 @@ func (p *process) SendExitMeta(alias gen.Alias, reason error) error { } atomic.AddUint64(&m.messagesIn, 1) + atomic.AddUint64(&metap.messagesIn, 1) atomic.AddUint64(&p.messagesOut, 1) m.handle() return nil @@ -1006,6 +1008,7 @@ func (p *process) SendExitMetaAfter(alias gen.Alias, reason error, after time.Du } atomic.AddUint64(&m.messagesIn, 1) + atomic.AddUint64(&metap.messagesIn, 1) atomic.AddUint64(&p.messagesOut, 1) m.handle() }).Stop, nil @@ -1320,6 +1323,7 @@ func (p *process) InspectMeta(alias gen.Alias, item ...string) (map[string]strin } atomic.AddUint64(&p.messagesOut, 1) atomic.AddUint64(&m.messagesIn, 1) + atomic.AddUint64(&metap.messagesIn, 1) if lib.Trace() { m.log.Trace("Inspect meta %s with %s", alias, ref) From 77bee297ba23a039ddb34a22a59ec5e5fb7b567d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 09:33:48 +0100 Subject: [PATCH 017/122] add ProcessInit time measurment (InitTime in ProcessInfo/ProcessShortInfo). fix message counters --- CHANGELOG.md | 3 +++ README.md | 6 ++++++ docs/extra-library/actors/metrics.md | 10 +++++----- gen/process.go | 6 ++++++ node/node.go | 8 ++++++++ node/process.go | 1 + 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa1f85a40..e3a4663c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and latency fields to `MailboxQueues` in `ProcessInfo`. See [Debugging](https://docs.ergo.services/advanced/debugging) documentation * Added **`Node.ProcessRangeShortInfo`** for efficient callback-based iteration over all processes with their current state. See [Metrics actor](https://docs.ergo.services/extra-library/actors/metrics) for Prometheus integration * Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` +* Added **process init time measurement** - `InitTime` field in `ProcessShortInfo` and `ProcessInfo` records the time spent in `ProcessInit` callback (nanoseconds) +* Fixed **message counters for meta processes** - meta process traffic now propagates to parent process counters, making `ProcessRangeShortInfo` aggregates balanced +* Fixed **self-send message counter** - `messagesOut` now incremented for self-sends #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index ae32474c6..e285cf540 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,12 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` +* Added **process init time measurement** - `InitTime` field in `ProcessShortInfo` and `ProcessInfo` records the time spent in `ProcessInit` callback (nanoseconds). Enables detection of slow process initialization + +* Fixed **message counters for meta processes** - meta process traffic now propagates to parent process counters (`messagesIn`/`messagesOut`), making `ProcessRangeShortInfo` aggregates balanced. Meta process own counters preserved for meta-level observability + +* Fixed **self-send message counter** - `messagesOut` now incremented for self-sends (process sending to itself), consistent with other send paths + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 4b6b5ce86..f87a7c554 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -60,7 +60,7 @@ When you spawn the metrics actor: 1. **HTTP endpoint starts** at the configured host and port. The `/metrics` endpoint immediately serves Prometheus-formatted data. -2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), per-process metrics (mailbox depth, utilization, latency, aggregates), and per-event metrics (subscriber distribution, delivery rates, waste patterns) update at the configured interval. +2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), per-process metrics (mailbox depth, utilization, latency, aggregates), and per-event metrics (utilization state, subscriber counts, delivery rates) update at the configured interval. 3. **Custom metrics update** via `CollectMetrics()` callback or `HandleMessage()` processing, depending on your implementation. @@ -437,15 +437,15 @@ The dashboard includes a `$node` variable dropdown that filters all panels by se The dashboard organizes metrics into logical groups arranged from high-level overview at the top to detailed breakdowns below. Rows marked "collapsed" are hidden by default -- click the row header to expand them. -**Summary Row** (expanded) - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. A gap between total and running processes indicates idle capacity or blocked processes. Non-zero zombies require investigation. +**Summary Row** (expanded) - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. The gap between total and running is normal -- most processes spend their time in Sleep state (idle, waiting for messages). Running counts only processes currently executing callbacks or waiting for a Call response. Non-zero zombies require investigation. **Mailbox Latency** (expanded, requires `-tags=latency`) - Six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". **Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." -**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Registered Events per Node and Max Subscribers per Node provide per-node breakdown. Event Publish Rate per Node and Event Delivery Rate per Node show where producers are most active and where fanout load concentrates. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. +**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. -**Process Activity** (collapsed) - Eight panels organized by topic: message throughput first, then process utilization. Message Throughput (Cluster Total) shows cluster-wide inbound and outbound message rates. Message Throughput per Node breaks this down by node. Top Processes by Inbound Rate and Top Processes by Outbound Rate show which actors currently receive and send the most messages per second -- derived from `rate()` on the per-process cumulative top-N metrics. Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Max Utilization per Node shows the busiest process on each node. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization; when this approaches CPU core count, the node is compute-saturated. Top Processes by Utilization table shows the busiest actors by lifetime utilization. +**Process Activity** (collapsed) - Eight panels organized by topic: message throughput first, then process utilization. Message Throughput (Cluster Total) shows cluster-wide inbound and outbound message rates. Message Throughput per Node breaks this down by node. Top Processes by Messages In and Top Processes by Messages Out tables identify which actors handle the most traffic (cumulative). Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Max Utilization per Node shows the busiest process on each node. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization; when this approaches CPU core count, the node is compute-saturated. Top Processes by Utilization table shows the busiest actors by lifetime utilization. **Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. @@ -512,7 +512,7 @@ Each metric group has a top-N panel in its row: - **Top Stressed Processes** (Latency row) -- processes with the highest mailbox latency. Answers "which process is the bottleneck?" - **Top Processes by Depth** (Mailbox Depth row) -- processes with the deepest queues. Answers "which process has the most messages waiting?" -- **Top Processes by Inbound/Outbound Rate** (Process Activity row) -- processes with the highest current message rate. Answers "which process handles the most traffic right now?" +- **Top Processes by Messages In/Out** (Process Activity row) -- processes with the most messages received or sent. Answers "which process handles the most traffic?" - **Top Processes by Utilization** (Process Activity row) -- processes that spend the most time in callbacks. Answers "which process is doing the most work?" Process tables show Application, Behavior, Name, PID, Node, and the metric value (plus Kubernetes labels when available). Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme values points to a specific process that needs investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques. diff --git a/gen/process.go b/gen/process.go index c3eb9bc75..343a211d0 100644 --- a/gen/process.go +++ b/gen/process.go @@ -912,6 +912,9 @@ type ProcessInfo struct { // RunningTime is the cumulative time spent in Running state (nanoseconds). RunningTime uint64 + // InitTime is the time spent in ProcessInit callback (nanoseconds). + InitTime uint64 + // Compression contains the compression configuration for this process. Compression Compression @@ -1022,6 +1025,9 @@ type ProcessShortInfo struct { // RunningTime is the cumulative time spent in Running state (nanoseconds). RunningTime uint64 + // InitTime is the time spent in ProcessInit callback (nanoseconds). + InitTime uint64 + // Uptime is the process uptime in seconds since creation. Uptime int64 diff --git a/node/node.go b/node/node.go index 68eb3e1c5..163ec592b 100644 --- a/node/node.go +++ b/node/node.go @@ -503,6 +503,7 @@ func (n *node) ProcessInfo(pid gen.PID) (gen.ProcessInfo, error) { info.MessagesIn = atomic.LoadUint64(&p.messagesIn) info.MessagesOut = atomic.LoadUint64(&p.messagesOut) info.RunningTime = atomic.LoadUint64(&p.runningTime) + info.InitTime = p.initTime info.Compression = p.compression info.MessagePriority = p.priority info.Uptime = p.Uptime() @@ -832,6 +833,7 @@ func (n *node) ProcessRangeShortInfo(fn func(gen.ProcessShortInfo) bool) error { MessagesMailbox: uint64(messagesMailbox), MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, + InitTime: p.initTime, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, @@ -1783,6 +1785,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MessagesMailbox: uint64(messagesMailbox), MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, + InitTime: p.initTime, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, @@ -1819,6 +1822,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MessagesMailbox: uint64(messagesMailbox), MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, + InitTime: p.initTime, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, @@ -2312,7 +2316,9 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra errCh := make(chan error, 1) go func() { + initStart := time.Now() err := behavior.ProcessInit(p, options.Args...) + p.initTime = uint64(time.Since(initStart)) // try to claim "init completed" if atomic.CompareAndSwapInt32(&completed, 0, 1) { @@ -2356,7 +2362,9 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra } } else { // no timeout - synchronous behavior + initStart := time.Now() initErr = behavior.ProcessInit(p, options.Args...) + p.initTime = uint64(time.Since(initStart)) } if initErr != nil { diff --git a/node/process.go b/node/process.go index f2832d4d0..d369c1513 100644 --- a/node/process.go +++ b/node/process.go @@ -43,6 +43,7 @@ type process struct { messagesIn uint64 messagesOut uint64 runningTime uint64 + initTime uint64 compression gen.Compression From 2de118802f66764c808e285653eb24dc03cdbea0 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 09:52:32 +0100 Subject: [PATCH 018/122] update docs --- docs/extra-library/actors/metrics.md | 130 +++++++++++++++++---------- 1 file changed, 84 insertions(+), 46 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index f87a7c554..d4ffe3fb8 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -217,6 +217,17 @@ No build tags required. Utilization metrics are always active. Distribution ranges: 1%, 5%, 10%, 25%, 50%, 75%, 90%, 90%+. Processes with zero running time or zero uptime are excluded. Utilization is capped at 1.0 (100%). +### Process Init Time Metrics + +The metrics actor tracks how long each process spent in its `ProcessInit` callback. This identifies actors with slow initialization -- heavy setup, blocking I/O, or synchronous calls during init. The default init timeout is 5 seconds (`DefaultRequestTimeout`), maximum 15 seconds for remote spawn. + +No build tags required. Init time metrics are always active. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_process_init_time_max_seconds` | Gauge | - | Maximum ProcessInit duration across all processes on this node. | +| `ergo_process_init_time_top_seconds` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by ProcessInit duration. | + ### Process Throughput Metrics The metrics actor tracks per-process message throughput (top-N by messages received and sent) and computes node-level aggregate counters by summing per-process values. @@ -262,7 +273,7 @@ The distinction between `published`, `local_sent`, and `remote_sent` in the top- ### Per-Process Metrics Collection -All per-process metrics (latency, depth, utilization, throughput, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. +All per-process metrics (latency, depth, utilization, throughput, init time, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. ## Custom Metrics @@ -447,7 +458,7 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Process Activity** (collapsed) - Eight panels organized by topic: message throughput first, then process utilization. Message Throughput (Cluster Total) shows cluster-wide inbound and outbound message rates. Message Throughput per Node breaks this down by node. Top Processes by Messages In and Top Processes by Messages Out tables identify which actors handle the most traffic (cumulative). Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Max Utilization per Node shows the busiest process on each node. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization; when this approaches CPU core count, the node is compute-saturated. Top Processes by Utilization table shows the busiest actors by lifetime utilization. -**Processes** (collapsed) - Four timeseries panels showing per-node process counts (total and running) and lifecycle rates (spawn rate with failures in red, termination rate). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. +**Processes** (collapsed) - Six panels showing per-node process counts (total and running), lifecycle rates (spawn rate with failures in red, termination rate), and initialization performance (init time bar gauge per node, top processes by init time). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. High init times indicate heavy initialization logic or blocking operations in ProcessInit. **Resources** (collapsed) - Four panels covering CPU and memory. CPU User Time and CPU System Time are normalized by core count and displayed as percentages. High user CPU means compute-bound workload; high system CPU relative to user suggests excessive I/O or syscalls. Memory (OS:used) and Memory (Runtime:alloc) show memory usage over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. @@ -457,79 +468,106 @@ The dashboard organizes metrics into logical groups arranged from high-level ove ### Working with the Dashboard -The dashboard is designed around a top-down investigation pattern. You start with high-level signals that tell you whether something is wrong, then drill into progressively more specific panels to understand what, where, and why. This section describes the investigation flow. +The dashboard is designed around a top-down investigation pattern. Start with the Summary row for cluster health, then drill into the relevant section based on the symptom you observe. #### Routine check -Open the dashboard and look at the Summary row. Six stat panels at the top answer the first question: is the cluster intact? +Open the dashboard and scan the Summary row: + +- **Zombie count should be zero.** Non-zero means processes have terminated abnormally and were not cleaned up. +- **Node count should match your expectation.** A drop means a node left the cluster. +- **Memory used should be within expected bounds.** A sharp increase suggests a leak or load spike. + +Then check the expanded rows below the Summary: + +- **Mailbox Latency** (if using `-tags=latency`) -- Max Latency under 100ms and Stressed Processes mostly empty or light-blue means healthy. If not using latency, check Mailbox Depth instead -- zero or low depth across all nodes is healthy. +- **Mailbox Depth** -- Max Depth per Node at zero or near zero is normal. + +For a deeper check, expand the collapsed rows: + +- **Events** -- Event Utilization should be mostly green (active) and blue (on demand). Growth in grey (idle) or orange (no subscribers) over time indicates accumulating waste. +- **Process Activity** -- Message Throughput should be stable. A sudden drop compared to the previous period may indicate stalled processes. -- **Zombie count should be zero.** Non-zero means processes have terminated abnormally and were not cleaned up. This requires immediate investigation. -- **Node count should match your expectation.** A missing node means it has left the cluster or lost connectivity. -- **Memory used should be within expected bounds.** A sharp increase since the last check suggests a leak or a load spike. +#### Investigating backpressure -If the Summary looks normal and you have latency enabled, glance at the Latency row directly below. If Max Latency is under 100ms and the Stressed Processes panel is mostly empty or light-blue -- the system is healthy. Routine check complete. +Backpressure means processes are receiving messages faster than they can handle them. The Mailbox Latency and Mailbox Depth rows are the primary tools. -If you are not using `-tags=latency`, check the Mailbox Depth row below. Max Depth per Node is the closest equivalent to Max Latency as a backpressure signal. If all nodes show zero or low depth, the system is healthy. For a deeper routine check, expand the Process Activity row and glance at Message Throughput -- a sudden drop compared to the previous period may indicate stalled processes even when depth looks normal. +**With `-tags=latency` enabled:** -#### Something is wrong: start with latency +Max Latency shows the worst case across the cluster. Stressed Processes shows how many processes are affected. Read them together: -When a problem is detected -- alerts fire, users report slowness, or the Summary shows unusual values -- the latency panels are the first place to investigate. They answer "are my actors keeping up with their workload?" +- Max Latency spikes above 1 second -- at least one process is severely behind. Use the Top Stressed Processes table to identify it. +- Orange area growing in Stressed Processes -- multiple processes are falling behind. Check Latency Distribution to assess severity (isolated red sliver = one stuck process, chart shifting to orange = widespread degradation). +- Max Latency persistently elevated (minutes, not seconds) -- a stuck process, not a burst. Find it in the Top Stressed Processes table. -If you are not using `-tags=latency`, skip to the Mailbox Depth row. Rising depth on a node means processes are receiving messages faster than they can handle them. Use the Depth Distribution panel to assess severity and the Top Processes by Depth table to identify the specific actors. Then continue with the "Understand severity" and "Correlate across panels" sections below -- they apply regardless of whether latency is enabled. +Use Max Latency per Node and Stressed Processes per Node to narrow down: one node standing out = localized problem; all nodes affected = systemic issue (shared dependency, deployment, cluster-wide traffic pattern). -The **Max Latency** panel shows the highest mailbox latency across all selected nodes as a red timeseries. Under normal conditions this stays under 100ms. Values above 1 second mean at least one process is significantly behind -- it is either overloaded, stuck in a long-running callback, or waiting for an external resource. +**Without latency tag:** -The **Stressed Processes** panel shows a stacked area chart with two layers. Light-blue represents processes with latency under 1ms (negligible, normal operation). Orange represents processes with latency of 1ms or above (worth investigating). A growing orange area means more processes are falling behind over time. +Max Depth per Node is the closest alternative. Rising depth means a process accumulates messages faster than it handles them. Depth Distribution shows severity. Top Processes by Depth identifies the specific actors. Depth is complementary to latency: depth tells you "how many messages are queued," latency tells you "how long the oldest has been waiting." -Read these two panels together: +#### Investigating throughput anomalies -- **Max Latency spikes above 1 second** -- at least one process is severely behind. Scroll down to the Top Stressed Processes table to identify it by application, behavior, name, and PID. -- **Orange area growing in Stressed Processes** -- multiple processes are accumulating latency. The problem is broader than a single actor. Check the Latency Distribution to understand severity, and the CPU panels to see if the system is compute-bound. -- **Max Latency spike followed by quick return to normal** -- a temporary burst. Compare timing with Process Spawn Rate in the Processes row to check for lifecycle event correlation. -- **Max Latency persistently elevated (minutes, not seconds)** -- a stuck process. Unlike overload (which fluctuates with traffic), a stuck process shows a steadily increasing or flat high value. Find it in the Top Stressed Processes table. +Expand the Process Activity row. The top two rows cover message throughput. -#### Narrow down: node or cluster? +- **Cluster Throughput drops suddenly** -- processes may be stalled or an upstream source stopped sending. Check if specific nodes dropped (Throughput per Node) or the entire cluster. +- **Cluster Throughput spikes** -- correlate with Mailbox Depth and Latency. A spike followed by growing depth means the system cannot absorb the burst. +- **In/Out imbalance** -- compare inbound and outbound rates. A persistent gap may indicate messages flowing to meta processes (not visible in process counters) or event fanout patterns. See the Events section for fanout analysis. +- **One node has disproportionate throughput** -- Throughput per Node identifies hotspots. Cross-reference with Top Processes by Messages In/Out to find the specific actors. -The **Max Latency per Node** and **Stressed Processes per Node** panels break the cluster-wide picture into individual nodes. +#### Investigating process lifecycle issues -If one node stands out while others are calm, the problem is localized. Cross-reference with Resources and Network panels for that node. A node with high max latency but low stressed count has one problematic process. A node with moderate latency but high stressed count is generally overloaded. +Expand the Processes row. -If multiple nodes show similar patterns, the problem is systemic -- a shared external dependency, a cluster-wide traffic pattern, or a deployment issue. +- **Steady growth in total process count** without plateau -- process leak. Processes are spawned but never terminated. Check which application spawns them using the process tables. +- **Spawn failures** (red in Process Spawn Rate) -- resource exhaustion or configuration errors preventing process creation. +- **Spawn rate spikes** -- may signal a supervisor restart loop. Correlate with termination rate -- if both spike together, a process keeps crashing and restarting. +- **Termination rate exceeds spawn rate** -- the node is draining. Check why processes are terminating (errors, shutdown, kills). +- **High init time** -- Max Init Time per Node shows the slowest ProcessInit on each node. Default timeout is 5 seconds. Top Processes by Init Time identifies which actor types take the longest. High init times indicate heavy setup, blocking I/O, or synchronous calls during initialization. If init times approach the timeout, processes risk being killed before they finish starting. -#### Understand severity: the distribution panels +#### Investigating event issues -The **Latency Distribution** panel shows a stacked area chart where each layer represents a latency range. Colors run from green (1ms-10ms, normal) through yellow (50ms-100ms, elevated) to orange (500ms-1s, concerning) and red (5s-60s+, critical). The legend is sorted from highest to lowest range. +Expand the Events row. -This panel distinguishes two scenarios that look similar in Max Latency: one stuck process (a single red sliver at the top of an otherwise green chart) versus widespread degradation (the entire chart shifting from green toward orange). The first requires investigating a specific process. The second requires scaling or load shedding. +- **Event Utilization shifting from green/blue to grey/orange** -- accumulating waste. Grey (idle) events are registered but unused. Orange (no subscribers) events are publishing into the void. Investigate which events are affected using the top-N tables. +- **Publish/Delivery Rate gap growing** -- Local Delivered >> Published indicates high fanout. If this correlates with latency increases on subscriber nodes, event fanout is causing backpressure. +- **One node has high Event Delivery Rate** -- that node handles the most event fanout. Cross-reference with Mailbox Depth and Latency for the same node. +- **Registered Events growing without plateau** -- event registration leak. Events are registered but never unregistered. Check Event Utilization for growing idle count. +- **Max Subscribers spike** -- one event suddenly gained many subscribers, amplifying the cost of each publish. -The **Depth Distribution** panel (in the Mailbox Depth row) provides a complementary view. Where latency distribution shows how long messages wait, depth distribution shows how many messages are queued. The color gradient follows the same flame convention: green for 1-10 messages, yellow for 50-100, red for 5K-10K+. A process with high depth but low latency processes messages quickly but receives many at once. A process with low depth but high latency is slow but not overwhelmed. +#### Investigating resource saturation -The **Utilization Distribution** panel (expand the Process Activity row) shows the fraction of lifetime each process spends inside callbacks. Most processes should be in the low ranges (1%-10%). A shift toward higher ranges (50%+) across many processes means the cluster is running compute-heavy workloads and may need scaling. +Expand the Resources row. -#### Find the specific process +- **CPU User Time approaching 100%** -- compute-bound. Correlate with Utilization Distribution in Process Activity to see which processes are consuming CPU. Actor Running Time per Node approaching CPU core count confirms saturation. +- **High System CPU relative to User CPU** -- excessive syscalls, context switching, or I/O pressure rather than application workload. +- **Memory monotonically growing** -- memory leak. Compare OS:used across nodes to spot outliers. Check if Mailbox Depth is also growing -- accumulating messages consume memory. +- **Runtime:alloc baseline rising between GC cycles** -- objects not being collected. The sawtooth pattern should return to a stable baseline. -Each metric group has a top-N panel in its row: +#### Investigating network issues -- **Top Stressed Processes** (Latency row) -- processes with the highest mailbox latency. Answers "which process is the bottleneck?" -- **Top Processes by Depth** (Mailbox Depth row) -- processes with the deepest queues. Answers "which process has the most messages waiting?" -- **Top Processes by Messages In/Out** (Process Activity row) -- processes with the most messages received or sent. Answers "which process handles the most traffic?" -- **Top Processes by Utilization** (Process Activity row) -- processes that spend the most time in callbacks. Answers "which process is doing the most work?" +Expand the Network row. -Process tables show Application, Behavior, Name, PID, Node, and the metric value (plus Kubernetes labels when available). Multiple entries from the same application suggest that application is under pressure as a whole. A single entry with extreme values points to a specific process that needs investigation -- see the [Debugging](../../advanced/debugging.md) section for techniques. +- **Cluster total message rate drops suddenly** -- possible network partition or node failure. Check Node count in Summary and per-node breakdown. +- **One node-pair has disproportionate traffic** -- Network Detail panels show traffic between specific pairs. Identifies saturated links or unexpected communication patterns. +- **Bytes-to-messages ratio changing** -- average message size is growing. May indicate serialization issues or bulk data transfers. -#### Correlate across panels +#### Cross-panel correlation -Individual metrics become most powerful when combined: +Combining signals from different sections identifies root causes: -- **High latency + high depth** -- the process is both slow and receiving more messages than it can handle. The mailbox is growing. This is the clearest sign of overload. -- **High latency + low depth** -- a single message is being processed slowly (long-running callback) or the process is blocked waiting for something. The mailbox is not growing because new messages are not arriving. -- **High depth + low latency** -- the process receives bursts but processes them quickly. The depth spikes are transient. Usually not a problem unless the bursts grow over time. -- **High latency + high CPU** -- processes are compute-bound. Actors are doing heavy work in callbacks and cannot keep up with the message rate. Consider distributing work across more processes or offloading expensive computation. -- **High latency + low CPU** -- processes are blocked on something other than computation. Common causes: waiting for external I/O, waiting for responses from other actors via synchronous calls, or contention on shared resources. -- **High latency + growing memory** -- mailboxes are accumulating messages faster than processes can handle them. The unprocessed messages consume memory. If this continues, the node will run out of memory. -- **High latency + network traffic spike** -- a burst of remote messages is overwhelming the receiving processes. Check Network per Node and Network Detail panels to identify the responsible link. -- **Running time per node approaching CPU core count** -- the node is compute-saturated. All available CPU time is spent inside actor callbacks. Either reduce the workload or add capacity. -- **Message throughput drop with stable process count** -- processes are alive but not doing work. They may be blocked on external calls or waiting for messages that are no longer arriving (upstream failure). +- **High latency + high depth** -- process is both slow and receiving more than it can handle. Mailbox growing. Clearest sign of overload. +- **High latency + low depth** -- single message processed slowly (long callback) or process blocked on external resource. Mailbox not growing. +- **High depth + low latency** -- process receives bursts but handles them quickly. Usually transient. +- **High latency + high CPU** -- compute-bound. Actors doing heavy work in callbacks. Distribute work or offload computation. +- **High latency + low CPU** -- processes blocked on something other than computation. External I/O, synchronous calls to other actors, or contention. +- **High latency + growing memory** -- mailboxes accumulating messages. If this continues, the node runs out of memory. +- **High latency + network traffic spike** -- burst of remote messages overwhelming receivers. Check Network Detail panels. +- **High event delivery rate + high latency on same node** -- event fanout causing backpressure. Top Events by Local Deliveries identifies which event, Mailbox Depth/Latency shows the impact on subscribers. +- **High init time + spawn rate spikes** -- supervisor restart loop with slow init. Each restart takes seconds, creating cascading delays. +- **Throughput drop + stable process count** -- processes alive but not doing work. Blocked on external calls or upstream failure (no messages arriving). +- **Running time per node approaching CPU cores** -- node is compute-saturated. All CPU time spent in actor callbacks. Reduce workload or add capacity. +- **Event no_subscribers growing + stable throughput** -- producers publishing into the void. Not using [Notify](../../basics/events.md) mechanism to detect absent subscribers. ## Observer Integration From 5b1ad46221d2a1729afee212bd1731f35e8e0159 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 10:04:18 +0100 Subject: [PATCH 019/122] update docs --- docs/extra-library/actors/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index d4ffe3fb8..b58c48299 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -523,7 +523,7 @@ Expand the Processes row. - **Spawn failures** (red in Process Spawn Rate) -- resource exhaustion or configuration errors preventing process creation. - **Spawn rate spikes** -- may signal a supervisor restart loop. Correlate with termination rate -- if both spike together, a process keeps crashing and restarting. - **Termination rate exceeds spawn rate** -- the node is draining. Check why processes are terminating (errors, shutdown, kills). -- **High init time** -- Max Init Time per Node shows the slowest ProcessInit on each node. Default timeout is 5 seconds. Top Processes by Init Time identifies which actor types take the longest. High init times indicate heavy setup, blocking I/O, or synchronous calls during initialization. If init times approach the timeout, processes risk being killed before they finish starting. +- **High init time** -- Init Time per Node bar gauge shows the slowest ProcessInit on each node with color-coded severity. Default timeout is 5 seconds. Top Processes by Init Time table identifies which actor types take the longest. High init times indicate heavy setup, blocking I/O, or synchronous calls during initialization. If init times approach the timeout, processes risk being killed before they finish starting. #### Investigating event issues From 0d7b4883ca9d2cf1bd8d2f1c52d9ffe83cf5575d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 21:11:13 +0100 Subject: [PATCH 020/122] add process wakeups counter --- gen/process.go | 8 ++++++++ node/node.go | 4 ++++ node/process.go | 2 +- node/process_run.go | 1 + node/process_run_pprof.go | 1 + 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gen/process.go b/gen/process.go index 343a211d0..52e3e17fb 100644 --- a/gen/process.go +++ b/gen/process.go @@ -915,6 +915,10 @@ type ProcessInfo struct { // InitTime is the time spent in ProcessInit callback (nanoseconds). InitTime uint64 + // Wakeups is the cumulative number of times the process transitioned + // from Sleep to Running state to handle messages. + Wakeups uint64 + // Compression contains the compression configuration for this process. Compression Compression @@ -1028,6 +1032,10 @@ type ProcessShortInfo struct { // InitTime is the time spent in ProcessInit callback (nanoseconds). InitTime uint64 + // Wakeups is the cumulative number of times the process transitioned + // from Sleep to Running state to handle messages. + Wakeups uint64 + // Uptime is the process uptime in seconds since creation. Uptime int64 diff --git a/node/node.go b/node/node.go index 163ec592b..c7f8eefb1 100644 --- a/node/node.go +++ b/node/node.go @@ -504,6 +504,7 @@ func (n *node) ProcessInfo(pid gen.PID) (gen.ProcessInfo, error) { info.MessagesOut = atomic.LoadUint64(&p.messagesOut) info.RunningTime = atomic.LoadUint64(&p.runningTime) info.InitTime = p.initTime + info.Wakeups = p.wakeups info.Compression = p.compression info.MessagePriority = p.priority info.Uptime = p.Uptime() @@ -834,6 +835,7 @@ func (n *node) ProcessRangeShortInfo(fn func(gen.ProcessShortInfo) bool) error { MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, InitTime: p.initTime, + Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, @@ -1786,6 +1788,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, InitTime: p.initTime, + Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, @@ -1823,6 +1826,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. MailboxLatency: p.mailbox.Latency(), RunningTime: p.runningTime, InitTime: p.initTime, + Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), Parent: p.parent, diff --git a/node/process.go b/node/process.go index d369c1513..730819e4e 100644 --- a/node/process.go +++ b/node/process.go @@ -44,6 +44,7 @@ type process struct { messagesOut uint64 runningTime uint64 initTime uint64 + wakeups uint64 compression gen.Compression @@ -853,7 +854,6 @@ func (p *process) SendEvent(name gen.Atom, token gen.Ref, message any) error { return err } - atomic.AddUint64(&p.messagesOut, 1) return nil } diff --git a/node/process_run.go b/node/process_run.go index 1d41a7b36..dcd0e2826 100644 --- a/node/process_run.go +++ b/node/process_run.go @@ -17,6 +17,7 @@ func (p *process) run() { int32(gen.ProcessStateRunning)) == false { // already running or terminated return } + atomic.AddUint64(&p.wakeups, 1) go func() { if lib.Recover() { defer func() { diff --git a/node/process_run_pprof.go b/node/process_run_pprof.go index 750250bfe..b1f2bd78c 100644 --- a/node/process_run_pprof.go +++ b/node/process_run_pprof.go @@ -19,6 +19,7 @@ func (p *process) run() { int32(gen.ProcessStateRunning)) == false { // already running or terminated return } + atomic.AddUint64(&p.wakeups, 1) go func() { labels := pprof.Labels("pid", p.pid.String()) pprof.Do(context.Background(), labels, func(context.Context) { From 4a23036dba7267898ad86d2c5b1b10574419995c Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 22:15:13 +0100 Subject: [PATCH 021/122] update docs --- docs/extra-library/actors/metrics.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index b58c48299..6d78b68df 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -244,6 +244,20 @@ Aggregate values are cumulative -- apply `rate()` in Prometheus to get per-secon `rate(ergo_process_messages_in)` and `rate(ergo_process_messages_out)` give the node-level message throughput in messages per second. `rate(ergo_process_running_time_seconds)` gives the node-level actor CPU utilization in seconds of callback execution per second -- when this value approaches the number of available CPU cores, the node is compute-saturated. +### Process Wakeups and Drains Metrics + +The metrics actor tracks process wakeups (transitions from Sleep to Running state) and drains (messages processed per wakeup). A wakeup occurs each time the framework starts a new goroutine to handle messages in a process's mailbox. The drain ratio (`MessagesIn / Wakeups`) reveals the nature of a process's load that utilization alone cannot distinguish. Two processes with 80% utilization may have completely different workloads: one with drain ~1 processes individual messages slowly (heavy per-message computation), while one with drain ~100 processes messages quickly but receives so many that it never sleeps (high throughput load). The optimization strategy is different: the first needs faster callbacks, the second needs load distribution. + +No build tags required. Wakeups and drains metrics are always active. + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_process_wakeups_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by cumulative wakeup count. | +| `ergo_process_drains_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by drain ratio (MessagesIn / Wakeups). | +| `ergo_process_wakeups` | Gauge | - | Sum of wakeups across all processes on this node. | + +On the dashboard, the Throughput panels show wakeup rate as a third line alongside message in/out rates -- the visual gap between message rate and wakeup rate represents the drain effect. Drains per Node timeseries shows per-node drain ratio over time computed from aggregate metrics: `rate(messages_in) / rate(wakeups)`. + ### Event Metrics The metrics actor collects per-event pub/sub metrics using `Node.EventRangeInfo()`, which iterates over all registered events and returns their current statistics. This provides visibility into the pub/sub layer: which events have the most subscribers, which generate the most delivery load, and which are wasteful. The subscriber count for each event includes both `LinkEvent` and `MonitorEvent` subscribers. @@ -273,7 +287,7 @@ The distinction between `published`, `local_sent`, and `remote_sent` in the top- ### Per-Process Metrics Collection -All per-process metrics (latency, depth, utilization, throughput, init time, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. +All per-process metrics (latency, depth, utilization, throughput, wakeups/drains, init time, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. ## Custom Metrics @@ -456,7 +470,7 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. -**Process Activity** (collapsed) - Eight panels organized by topic: message throughput first, then process utilization. Message Throughput (Cluster Total) shows cluster-wide inbound and outbound message rates. Message Throughput per Node breaks this down by node. Top Processes by Messages In and Top Processes by Messages Out tables identify which actors handle the most traffic (cumulative). Utilization Distribution is a stacked area chart showing how many processes fall into each utilization range (1% through 90%+), using a flame gradient from green to red. Max Utilization per Node shows the busiest process on each node. Actor Running Time per Node shows `rate(running_time_seconds)` per node -- effectively the node-level actor CPU utilization; when this approaches CPU core count, the node is compute-saturated. Top Processes by Utilization table shows the busiest actors by lifetime utilization. +**Process Activity** (collapsed) - Ten panels organized by topic: message throughput, drains, then process utilization. Message Throughput (Cluster Total) and Message Throughput per Node show inbound, outbound, and wakeup rates -- the gap between message rate and wakeup rate reveals drain effect (processes batching under load). Top Processes by Messages In/Out tables identify which actors handle the most traffic. Drains per Node timeseries shows per-node drain ratio over time (`rate(messages_in) / rate(wakeups)`), and Top Processes by Drains table identifies specific actors with the highest drain -- these are the processes that handle the most messages per wakeup cycle. Drain ratio complements utilization: two processes at 80% utilization may have drain ~1 (slow callbacks) or drain ~100 (fast callbacks, high volume) -- different problems needing different solutions. Utilization Distribution, Max Utilization per Node, Actor Running Time per Node, and Top Processes by Utilization cover compute load analysis. **Processes** (collapsed) - Six panels showing per-node process counts (total and running), lifecycle rates (spawn rate with failures in red, termination rate), and initialization performance (init time bar gauge per node, top processes by init time). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. High init times indicate heavy initialization logic or blocking operations in ProcessInit. @@ -514,6 +528,7 @@ Expand the Process Activity row. The top two rows cover message throughput. - **Cluster Throughput spikes** -- correlate with Mailbox Depth and Latency. A spike followed by growing depth means the system cannot absorb the burst. - **In/Out imbalance** -- compare inbound and outbound rates. A persistent gap may indicate messages flowing to meta processes (not visible in process counters) or event fanout patterns. See the Events section for fanout analysis. - **One node has disproportionate throughput** -- Throughput per Node identifies hotspots. Cross-reference with Top Processes by Messages In/Out to find the specific actors. +- **Wakeup rate diverges from message rate** -- on Throughput panels, the gap between In and Wakeups lines shows drain effect. Growing gap means processes batch more messages per wakeup (increasing load). Drains per Node timeseries shows which node, Top Processes by Drains shows which process. #### Investigating process lifecycle issues @@ -568,6 +583,10 @@ Combining signals from different sections identifies root causes: - **Throughput drop + stable process count** -- processes alive but not doing work. Blocked on external calls or upstream failure (no messages arriving). - **Running time per node approaching CPU cores** -- node is compute-saturated. All CPU time spent in actor callbacks. Reduce workload or add capacity. - **Event no_subscribers growing + stable throughput** -- producers publishing into the void. Not using [Notify](../../basics/events.md) mechanism to detect absent subscribers. +- **High drain + stable depth** -- process running at maximum capacity but keeping up. No action needed unless depth starts growing. +- **High drain + growing depth** -- process cannot keep up despite continuous processing. Needs load distribution or faster message handling. +- **High utilization + low drain** -- slow per-message processing. Each callback takes long. Optimize the callback logic. +- **High utilization + high drain** -- fast processing but overwhelming volume. Distribute load across more processes. ## Observer Integration From cf57b315bc62fba7e247116d99ddeee50f136ddb Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 23:07:43 +0100 Subject: [PATCH 022/122] update docs --- docs/extra-library/actors/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 6d78b68df..40ab53086 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -526,7 +526,7 @@ Expand the Process Activity row. The top two rows cover message throughput. - **Cluster Throughput drops suddenly** -- processes may be stalled or an upstream source stopped sending. Check if specific nodes dropped (Throughput per Node) or the entire cluster. - **Cluster Throughput spikes** -- correlate with Mailbox Depth and Latency. A spike followed by growing depth means the system cannot absorb the burst. -- **In/Out imbalance** -- compare inbound and outbound rates. A persistent gap may indicate messages flowing to meta processes (not visible in process counters) or event fanout patterns. See the Events section for fanout analysis. +- **In/Out imbalance** -- in a fully monitored cluster (metrics actor on every node), In and Out should be approximately balanced. A small imbalance is normal due to framework-internal messages (exit signals, down notifications) that increment In without a corresponding Out. Persistent significant imbalance indicates nodes without metrics collection: Out > In means messages are sent to unmonitored nodes, In > Out means unmonitored nodes are sending messages into the cluster. - **One node has disproportionate throughput** -- Throughput per Node identifies hotspots. Cross-reference with Top Processes by Messages In/Out to find the specific actors. - **Wakeup rate diverges from message rate** -- on Throughput panels, the gap between In and Wakeups lines shows drain effect. Growing gap means processes batch more messages per wakeup (increasing load). Drains per Node timeseries shows which node, Top Processes by Drains shows which process. From cb4e7499386a46e24f25231506354beec2dc17a3 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Feb 2026 23:29:59 +0100 Subject: [PATCH 023/122] fix event published double-counting: split into EventsPublished (local producers) and EventReceived (remote arrivals) --- CHANGELOG.md | 2 +- README.md | 2 +- docs/basics/events.md | 2 +- docs/extra-library/actors/metrics.md | 5 +++-- gen/node.go | 5 ++++- gen/target.go | 3 ++- node/node.go | 1 + node/tm/event.go | 4 ++-- node/tm/manager.go | 2 ++ 9 files changed, 17 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a4663c0..bdf584dc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added **process lifecycle counters** to `gen.NodeInfo` - `ProcessesSpawned`, `ProcessesSpawnFailed`, `ProcessesTerminated` for cumulative statistics * Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and latency fields to `MailboxQueues` in `ProcessInfo`. See [Debugging](https://docs.ergo.services/advanced/debugging) documentation * Added **`Node.ProcessRangeShortInfo`** for efficient callback-based iteration over all processes with their current state. See [Metrics actor](https://docs.ergo.services/extra-library/actors/metrics) for Prometheus integration -* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` +* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsReceived`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo`. `EventsPublished` counts only local producer publishes, `EventsReceived` counts events arriving from remote nodes * Added **process init time measurement** - `InitTime` field in `ProcessShortInfo` and `ProcessInfo` records the time spent in `ProcessInit` callback (nanoseconds) * Fixed **message counters for meta processes** - meta process traffic now propagates to parent process counters, making `ProcessRangeShortInfo` aggregates balanced * Fixed **self-send message counter** - `messagesOut` now incremented for self-sends diff --git a/README.md b/README.md index e285cf540..a9d50f26b 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **mailbox latency measurement** (build with `-tags=latency`). `QueueMPSC.Latency()` returns the age of the oldest message in the queue (nanoseconds), -1 if disabled. `ProcessMailbox.Latency()` returns the max across all four queues. Added `MailboxLatency` field to `ProcessShortInfo` and `MailboxQueues` latency fields to `ProcessInfo`. Added `Node.ProcessRangeShortInfo` for efficient iteration over all processes. See [actor/metrics](https://github.com/ergo-services/actor-metrics) for Prometheus integration with histogram, top-N, and Grafana dashboard -* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo` +* Added **per-event metrics** - `EventInfo` now includes `MessagesPublished`, `MessagesLocalSent`, `MessagesRemoteSent` counters. Added `Node.EventInfo` and `Node.EventRangeInfo` for querying event statistics. Added `EventsPublished`, `EventsReceived`, `EventsLocalSent`, `EventsRemoteSent` to `NodeInfo`. `EventsPublished` counts only local producer publishes, `EventsReceived` counts events arriving from remote nodes * Added **process init time measurement** - `InitTime` field in `ProcessShortInfo` and `ProcessInfo` records the time spent in `ProcessInit` callback (nanoseconds). Enables detection of slow process initialization diff --git a/docs/basics/events.md b/docs/basics/events.md index 392aef5ff..dac47af93 100644 --- a/docs/basics/events.md +++ b/docs/basics/events.md @@ -132,7 +132,7 @@ node.EventRangeInfo(func(info gen.EventInfo) bool { }) ``` -Node-level aggregate counters are also available in `gen.NodeInfo` via `node.Info()`: `EventsPublished`, `EventsLocalSent`, and `EventsRemoteSent` sum across all events on the node. +Node-level aggregate counters are also available in `gen.NodeInfo` via `node.Info()`: `EventsPublished` (local producer publishes), `EventsReceived` (events arriving from remote nodes), `EventsLocalSent`, and `EventsRemoteSent`. The [Metrics actor](../extra-library/actors/metrics.md) automatically exports these counters as Prometheus metrics, along with per-event top-N breakdowns by subscribers, published, local deliveries, and remote sent. It also tracks event utilization state -- whether events are actively used, waiting on demand, or idle. diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 40ab53086..fa9dbb873 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -149,7 +149,8 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_registered_names_total` | Gauge | Processes registered with atom names. High counts suggest heavy use of named processes for routing. | | `ergo_registered_aliases_total` | Gauge | Total number of registered aliases. Includes aliases created by processes via `CreateAlias()` and aliases identifying meta-processes. | | `ergo_registered_events_total` | Gauge | Total number of registered events on this node. | -| `ergo_events_published_total` | Gauge | Cumulative number of events published on this node. Includes both local producer publishes and events arriving from remote nodes. Use `rate()` to get publish throughput. | +| `ergo_events_published_total` | Gauge | Cumulative number of events published by local producers. Use `rate()` to get publish throughput. | +| `ergo_events_received_total` | Gauge | Cumulative number of events received from remote nodes. Shows incoming event traffic load. | | `ergo_events_local_sent_total` | Gauge | Cumulative number of event messages delivered to local subscribers. This reflects the actual fanout load -- a single publish with 100 subscribers produces 100 local deliveries. | | `ergo_events_remote_sent_total` | Gauge | Cumulative number of event messages sent to remote nodes. Due to shared subscription optimization, one message is sent per remote node regardless of how many subscribers that node has. See [Pub/Sub Internals](../../advanced/pub-sub-internals.md). | @@ -468,7 +469,7 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." -**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with three lines: Published (how often producers publish), Local Delivered (actual fanout to local subscribers -- typically much higher than Published when events have many subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. +**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with four lines: Published (local producer publish rate), Received (events arriving from remote nodes), Local Delivered (actual fanout to local subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. **Process Activity** (collapsed) - Ten panels organized by topic: message throughput, drains, then process utilization. Message Throughput (Cluster Total) and Message Throughput per Node show inbound, outbound, and wakeup rates -- the gap between message rate and wakeup rate reveals drain effect (processes batching under load). Top Processes by Messages In/Out tables identify which actors handle the most traffic. Drains per Node timeseries shows per-node drain ratio over time (`rate(messages_in) / rate(wakeups)`), and Top Processes by Drains table identifies specific actors with the highest drain -- these are the processes that handle the most messages per wakeup cycle. Drain ratio complements utilization: two processes at 80% utilization may have drain ~1 (slow callbacks) or drain ~100 (fast callbacks, high volume) -- different problems needing different solutions. Utilization Distribution, Max Utilization per Node, Actor Running Time per Node, and Top Processes by Utilization cover compute load analysis. diff --git a/gen/node.go b/gen/node.go index 1f094598f..a6e957ea2 100644 --- a/gen/node.go +++ b/gen/node.go @@ -763,9 +763,12 @@ type NodeInfo struct { // RegisteredEvents is the total number of registered events. RegisteredEvents int64 - // EventsPublished is the cumulative number of events published. + // EventsPublished is the cumulative number of events published by local producers. EventsPublished int64 + // EventsReceived is the cumulative number of events received from remote nodes. + EventsReceived int64 + // EventsLocalSent is the cumulative number of event messages sent to local subscribers. EventsLocalSent int64 diff --git a/gen/target.go b/gen/target.go index f854194c5..ae6c35891 100644 --- a/gen/target.go +++ b/gen/target.go @@ -75,7 +75,8 @@ type TargetManagerInfo struct { ExitSignalsDelivered int64 // Total exit signals delivered by dispatchers DownMessagesProduced int64 // Total down messages generated DownMessagesDelivered int64 // Total down messages delivered - EventsPublished int64 // Total events published + EventsPublished int64 // Total events published by local producers + EventsReceived int64 // Total events received from remote nodes EventsLocalSent int64 // Total event messages sent to local subscribers EventsRemoteSent int64 // Total event messages sent to remote subscribers } diff --git a/node/node.go b/node/node.go index c7f8eefb1..f5d4749c2 100644 --- a/node/node.go +++ b/node/node.go @@ -722,6 +722,7 @@ func (n *node) Info() (gen.NodeInfo, error) { tmInfo := n.targets.Info() info.RegisteredEvents = tmInfo.Events info.EventsPublished = tmInfo.EventsPublished + info.EventsReceived = tmInfo.EventsReceived info.EventsLocalSent = tmInfo.EventsLocalSent info.EventsRemoteSent = tmInfo.EventsRemoteSent diff --git a/node/tm/event.go b/node/tm/event.go index e60709f82..410fa8499 100644 --- a/node/tm/event.go +++ b/node/tm/event.go @@ -264,8 +264,8 @@ func (tm *targetManager) publishEventRemoteProducer( return nil } - // Increment published counter - tm.eventsPublished.Add(1) + // Increment received counter (remote event arrival, not a local publish) + tm.eventsReceived.Add(1) // Collect local consumers for batch delivery var localConsumers []gen.PID diff --git a/node/tm/manager.go b/node/tm/manager.go index b112e9b0f..ae6a57cd1 100644 --- a/node/tm/manager.go +++ b/node/tm/manager.go @@ -28,6 +28,7 @@ type targetManager struct { downMessagesProduced atomic.Int64 downMessagesDelivered atomic.Int64 eventsPublished atomic.Int64 + eventsReceived atomic.Int64 eventsLocalSent atomic.Int64 eventsRemoteSent atomic.Int64 } @@ -95,6 +96,7 @@ func (tm *targetManager) Info() gen.TargetManagerInfo { DownMessagesProduced: tm.downMessagesProduced.Load(), DownMessagesDelivered: tm.downMessagesDelivered.Load(), EventsPublished: tm.eventsPublished.Load(), + EventsReceived: tm.eventsReceived.Load(), EventsLocalSent: tm.eventsLocalSent.Load(), EventsRemoteSent: tm.eventsRemoteSent.Load(), } From 93b01d65d0a712bf692b26cdcbeda980b2a1ed32 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Feb 2026 09:31:27 +0100 Subject: [PATCH 024/122] add edf.RegisteredTypes edf.LookupType --- net/edf/register.go | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/net/edf/register.go b/net/edf/register.go index 2006bbe3d..da35e6ca4 100644 --- a/net/edf/register.go +++ b/net/edf/register.go @@ -727,6 +727,53 @@ func addRegCache(t reflect.Type) error { return nil } +// RegisteredTypes returns all registered types as a map of +// type name (format: "#pkgpath/TypeName") to reflect.Type. +// This allows external tools (like MCP server) to discover and +// construct registered message types via reflection. +func RegisteredTypes() map[string]reflect.Type { + result := make(map[string]reflect.Type) + decoders.Range(func(k, v any) bool { + name, ok := k.(string) + if ok == false { + return true + } + dec := v.(*decoder) + result[name] = dec.Type + return true + }) + return result +} + +// LookupType returns the reflect.Type for a registered type by name. +// The name can be a full EDF name ("#pkgpath/TypeName") or a short +// type name ("TypeName") which matches the first type with that suffix. +func LookupType(name string) (reflect.Type, bool) { + // Try exact match first + if v, ok := decoders.Load(name); ok { + return v.(*decoder).Type, true + } + + // Try short name match (suffix match on "/TypeName") + suffix := "/" + name + var found reflect.Type + decoders.Range(func(k, v any) bool { + s, ok := k.(string) + if ok == false { + return true + } + if len(s) > len(suffix) && s[len(s)-len(suffix):] == suffix { + found = v.(*decoder).Type + return false + } + return true + }) + if found != nil { + return found, true + } + return nil, false +} + func GetRegCache() map[uint16]string { cache := make(map[uint16]string) regCache.Range(func(k, v any) bool { From c53528eb52e6e31c0a4ef1b038dcd4b64964f146 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Feb 2026 09:56:06 +0100 Subject: [PATCH 025/122] update docs --- docs/SUMMARY.md | 1 + docs/extra-library/applications/mcp.md | 246 +++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 docs/extra-library/applications/mcp.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ec15d0c42..c14dd0387 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -64,6 +64,7 @@ * [Metrics](extra-library/actors/metrics.md) * [Applications](extra-library/applications/README.md) * [Observer](extra-library/applications/observer.md) + * [MCP](extra-library/applications/mcp.md) * [Meta-Processes](extra-library/meta-processes/README.md) * [WebSocket](extra-library/meta-processes/websocket.md) * [SSE](extra-library/meta-processes/sse.md) diff --git a/docs/extra-library/applications/mcp.md b/docs/extra-library/applications/mcp.md new file mode 100644 index 000000000..720b211ef --- /dev/null +++ b/docs/extra-library/applications/mcp.md @@ -0,0 +1,246 @@ +# MCP + +The MCP application is a sidecar diagnostic tool for Ergo Framework nodes. It runs inside your node as a regular Ergo application and exposes 46 inspection tools via MCP (Model Context Protocol) over HTTP. AI agents like Claude Code connect to the endpoint and use these tools to diagnose performance bottlenecks, inspect processes, profile goroutines and heap, monitor metrics in real time, and trace issues across a cluster -- all without restarting or redeploying the node. + +The application has two deployment modes. An **entry point** node runs an HTTP listener that accepts MCP requests. An **agent** node has no HTTP listener but is fully accessible through the entry point via cluster proxy. This means a single HTTP endpoint gives access to every node in the cluster. + +The real power comes from combining MCP with other context the AI agent already has. When the agent can see your source code, inspect a live cluster in real time, and query your log storage (OpenSearch, Loki, CloudWatch) -- it connects the dots that no single tool can. It reads the actor implementation, checks its runtime state via MCP, correlates with error logs, and pinpoints the root cause. Source code explains intent. MCP shows what actually happens. Logs show the history. Together they eliminate guesswork. + +## Why MCP + +Traditional monitoring tools (Prometheus, Grafana) collect predefined metrics at fixed intervals and display them on dashboards. You decide upfront what to track, configure scraping, build dashboards, and then interpret the data yourself when something goes wrong. + +MCP takes a different approach. Instead of predefined metrics, it exposes the full diagnostic API of the node -- 46 tools covering processes, applications, events, network, runtime, and profiling. An AI agent decides what to inspect based on the symptom you describe. It runs diagnostic sequences, correlates findings across tools, and narrows down root causes interactively. + +This is particularly useful for: + +- **Source code + live cluster + logs** -- the agent reads your actor code to understand what a process should do, inspects it via MCP to see what it actually does, and checks logs to see what happened before. This combination is far more powerful than any of these tools in isolation. +- **Ad-hoc investigation** -- you don't need to have anticipated the problem. The agent explores the node's state dynamically. +- **Distributed tracing** -- the cluster proxy lets the agent inspect any node from a single entry point, following issues across node boundaries. +- **Real-time sampling** -- active samplers periodically call any tool and store results in a ring buffer. Passive samplers capture log streams and event publications as they happen. The agent reads collected data incrementally. +- **Deep profiling** -- goroutine stack traces per process PID (with `-tags=pprof`), heap profiling, runtime stats, all accessible through tool calls. + +MCP complements rather than replaces traditional monitoring. Use Prometheus/Grafana for long-term trends and alerting, and MCP for interactive investigation when alerts fire. + +## Adding to Your Node + +```goimport ( + "ergo.services/ergo" + "ergo.services/application/mcp" + "ergo.services/ergo/gen" +) + +func main() { + opt := gen.NodeOptions{ + Applications: []gen.ApplicationBehavior{ + mcp.CreateApp(mcp.Options{ + Port: 9922, + }), + }, + } + node, err := ergo.StartNode("example@localhost", opt) + if err != nil { + panic(err) + } + node.Wait() +} +``` + +The function `mcp.CreateApp` takes `mcp.Options` as an argument: + +* **Port**: The port number for the HTTP endpoint (default: `0` which means agent mode -- no HTTP listener). +* **Host**: The interface name (default: `localhost`). +* **Token**: Bearer token for authentication. Empty string disables authentication. +* **ReadOnly**: When `true`, disables action tools (`send_message`, `call_process`, `send_exit`, `process_kill`). Useful for production nodes where you want inspection without the ability to modify state. +* **AllowedTools**: A whitelist of tool names. When set, only the listed tools are available. `nil` or empty means all tools are enabled (respecting `ReadOnly`). +* **PoolSize**: The number of worker processes that handle incoming requests (default: `5`). +* **LogLevel**: The logging level for the MCP application processes. + +## Connecting a Client + +### Claude Code + +```bash +# Add the MCP server +claude mcp add --transport http ergo http://localhost:9922/mcp + +# With authentication +claude mcp add --transport http ergo http://localhost:9922/mcp \ + -H "Authorization: Bearer my-secret-token" +``` + +To allow all MCP tools without per-call permission prompts, add to `.claude/settings.json`: + +```json +{ + "permissions": { + "allow": [ + "mcp__ergo" + ] + } +} +``` + +The prefix `mcp__ergo` matches the server name from the `claude mcp add` command. Once configured, the agent can call any of the 46 tools directly. + +### Other MCP Clients + +The application implements MCP protocol version `2025-06-18` over HTTP. Any MCP-compatible client can connect by sending JSON-RPC 2.0 POST requests to `http://:/mcp`. + +## What You Can Do + +The 46 tools are organized into categories. You don't need to learn them -- the agent discovers available tools automatically via the MCP protocol. But understanding the categories helps you know what kinds of questions you can ask. + +Every tool accepts an optional `node` parameter for cluster proxy. When specified and the target is a different node, the request is forwarded via native Ergo inter-node protocol. + +### Inspect node and processes + +The most common starting point. Ask the agent to show you what's happening on the node -- process counts, memory, CPU, running applications. Then drill into individual processes: who has the deepest mailbox, who consumes the most CPU, who was recently spawned. + +Example prompts: +- "Show me the overall health of the node" +- "Which processes have the deepest mailboxes right now?" +- "Find processes that were spawned in the last 30 seconds" +- "Show me the supervision tree under the order_sup process" +- "What's the state of process worker_3?" + +The `process_list` tool supports filtering (by application, behavior, state, name, numeric thresholds) and sorting (by mailbox depth, latency, running time, wakeups, drain ratio, etc.). This makes it the primary instrument for finding problematic processes. + +### Monitor applications and events + +Check application lifecycle (loaded, running, stopped), inspect dependencies, and diagnose pub/sub event issues. The event tools detect common problems: events publishing to nobody, subscribers waiting for data that never comes, fanout overload. + +Example prompts: +- "Which applications are running? Any stopped?" +- "Show me events that have no subscribers" +- "Which events generate the most inter-node traffic?" +- "List all events owned by the order_handler process" + +### Diagnose network and cluster + +Inspect cluster connectivity, traffic between nodes, registrar state, and routes. Connect or disconnect nodes. The cluster proxy means you can inspect any node from a single entry point. + +Example prompts: +- "Show me all nodes in the cluster and their status" +- "Is node backend@host connected? What's the traffic like?" +- "Connect to node worker@host and show its process list" +- "Check if the payment-service application is deployed across the cluster" + +### Profile and debug + +Deep diagnostics: goroutine stack traces (per-process with `-tags=pprof`), heap profiling, runtime stats. Find deadlocks, goroutine leaks, memory pressure. + +Example prompts: +- "Show me the goroutine dump, group by stack" +- "Get the stack trace of process order_handler" (requires `-tags=pprof`) +- "What's the heap profile? Who allocates the most?" +- "Are there any processes stuck in WaitResponse?" + +When a process is sleeping, its goroutine is parked and won't appear in the dump. The agent can use a sampler to poll until the process wakes up. + +### Sample metrics over time + +Snapshots are useful but trends tell the real story. Active samplers periodically call any tool and store results in a ring buffer. Passive samplers capture log messages and event publications as they happen. + +Example prompts: +- "Monitor the top 10 mailbox offenders for 5 minutes" +- "Track memory and GC stats every 5 seconds" +- "Capture error and panic logs for the next 2 minutes" +- "Subscribe to the order_events event and show me what gets published" +- "Try to catch the goroutine of process worker_5 -- it's usually sleeping" + +Active samplers are generic -- any tool can be sampled with any arguments. The `max_errors=0` parameter makes the sampler ignore errors and keep retrying, which is useful for polling rare conditions (like catching a sleeping process goroutine). All samplers are time-limited (default 60 seconds, maximum 1 hour). + +### Manage log levels + +Change log verbosity at runtime without restarting. Target the entire node, a specific process, or a meta process. + +Example prompts: +- "Set debug logging on the payment_handler process" +- "What's the current log level for the node?" +- "List all registered loggers" + +### Send messages and interact (action tools) + +When `ReadOnly` is not set, the agent can send messages to processes, make synchronous calls with typed payloads from the EDF registry, send exit signals, and kill processes. These tools require explicit user permission. + +Example prompts: +- "Send a StatusRequest to the worker_1 process and show the response" +- "What message types are registered in EDF?" +- "Gracefully stop the stuck_process with a shutdown signal" + +The agent uses EDF type registry to construct typed Go structs from JSON. For example, if your application registers a `StatusRequest` type: + +```go +// In your application code +type StatusRequest struct { + Verbose bool +} + +func init() { + edf.RegisterTypeOf(StatusRequest{}) +} +``` + +The agent can discover it with `message_types`, inspect its fields with `message_type_info`, and send it: + +``` +> Send a StatusRequest with Verbose=true to worker_1 + +Agent calls: message_type_info(type_name="StatusRequest") + -> Fields: Verbose (bool) + +Agent calls: call_process(to="worker_1", type_name="StatusRequest", request={"Verbose": true}) + -> Response: {"Status": "running", "Uptime": 3600} +``` + +The process receives a real `StatusRequest{Verbose: true}` Go struct in its `HandleCall` -- not raw JSON. The EDF registry handles the reflection and construction. + +## Cluster Proxy + +Every tool accepts a `node` parameter. When specified and the target differs from the local node, the request is forwarded to the remote node's MCP pool via native Ergo inter-node protocol -- not HTTP. The remote node must have the MCP application running, but agent mode (no HTTP) is sufficient. + +This means you deploy one entry point node with HTTP and configure all other nodes as agents: + +```go// Entry point node -- has HTTP listener +mcp.CreateApp(mcp.Options{Port: 9922}) + +// Agent nodes -- no HTTP, accessible via cluster proxy +mcp.CreateApp(mcp.Options{}) +``` + +The agent connects to `http://entry-point:9922/mcp` and reaches any node in the cluster through the entry point. Connection between nodes happens through the standard Ergo network layer (registrar, static routes, or explicit connect). + +## Build Tags + +Two build tags enable additional diagnostic capabilities: + +**`-tags=pprof`** enables per-process goroutine stack traces. When built with this tag, actor goroutines are labeled with their process PID via `runtime/pprof` labels. The `pprof_goroutines` tool with `pid` parameter extracts the stack trace of a specific actor's goroutine. Without this tag, the `pid` parameter returns an error. + +**`-tags=latency`** enables mailbox latency measurement. The `process_list` tool gains `min_mailbox_latency_ms` filter and `mailbox_latency` sort field. Each process reports `MailboxLatency` -- how long the oldest message has been waiting in the mailbox. Without this tag, latency fields return -1. + +Both tags add a small amount of overhead. Enable them in staging and production builds where diagnostics matter. + +## Relationship to Metrics Actor + +The [Metrics](../actors/metrics.md) actor collects predefined metrics into Prometheus format for scraping by external monitoring systems. The MCP application provides the same underlying data (it reads from `ProcessRangeShortInfo`, `NodeInfo`, `EventRangeInfo` -- the same sources) but exposes it interactively through tool calls. + +Active samplers can replicate what the metrics actor does -- `sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10}` is equivalent to the `ergo_mailbox_depth_top` Prometheus metric. The key difference is that MCP samplers are on-demand and agent-driven, while Prometheus metrics are always-on and scraper-driven. + +Use the metrics actor when you need long-term time-series storage, alerting rules, and Grafana dashboards. Use MCP when you need interactive investigation, ad-hoc queries, and AI-assisted diagnostics. + +## Agent and Skill for Claude Code + +A ready-to-use Claude Code agent and skill are available at [github.com/ergo-services/claude](https://github.com/ergo-services/claude): + +* **ergo-devops agent** (`claude/agents/ergo-devops.md`) -- interactive diagnostics agent that connects to a running node via MCP and runs diagnostic sequences. Contains playbooks for performance bottlenecks, process leaks, restart loops, zombie processes, memory growth, network issues, event system problems, goroutine investigation, and cluster health checks. Trigger it by describing a symptom ("why is it slow", "check the cluster", "find process leak"). + +* **ergo-devops skill** (`claude/skills/ergo-devops/SKILL.md`) -- compact reference with the same playbooks in recipe format, pattern matching tables, and sampler quick reference. Load it via `/ergo-devops` in Claude Code for quick lookup without starting a full investigation. + +Install by symlinking into `~/.claude/`: + +```bash +cd ergo.services/claude +ln -sf $(pwd)/agents/ergo-devops.md ~/.claude/agents/ +ln -sf $(pwd)/skills/ergo-devops ~/.claude/skills/ +``` From deac46da84b5cc019dd765eb9aeeefb86cbe718e Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Feb 2026 09:58:03 +0100 Subject: [PATCH 026/122] update docs --- docs/extra-library/applications/mcp.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/extra-library/applications/mcp.md b/docs/extra-library/applications/mcp.md index 720b211ef..11caceef2 100644 --- a/docs/extra-library/applications/mcp.md +++ b/docs/extra-library/applications/mcp.md @@ -24,7 +24,8 @@ MCP complements rather than replaces traditional monitoring. Use Prometheus/Graf ## Adding to Your Node -```goimport ( +```go +import ( "ergo.services/ergo" "ergo.services/application/mcp" "ergo.services/ergo/gen" From 976794dcefd7e0994d2e1a03038151b827520b9d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Feb 2026 12:29:54 +0100 Subject: [PATCH 027/122] add ServerTime to gen.NodeInfo --- gen/node.go | 4 ++++ node/node.go | 2 ++ 2 files changed, 6 insertions(+) diff --git a/gen/node.go b/gen/node.go index a6e957ea2..4edf327cb 100644 --- a/gen/node.go +++ b/gen/node.go @@ -792,6 +792,10 @@ type NodeInfo struct { // SystemTime is the system CPU time in nanoseconds. SystemTime int64 + + // ServerTime is the current server time with timezone. + // Useful in Observer and MCP for correlating logs across nodes in different timezones. + ServerTime time.Time } // LoggerInfo describes a registered logger. diff --git a/node/node.go b/node/node.go index f5d4749c2..805e3d508 100644 --- a/node/node.go +++ b/node/node.go @@ -738,6 +738,8 @@ func (n *node) Info() (gen.NodeInfo, error) { info.UserTime = utime info.SystemTime = stime + info.ServerTime = time.Now() + return info, nil } From 2787915bb93c947f040a410815dea469bacc1735 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Feb 2026 18:16:31 +0100 Subject: [PATCH 028/122] update docs --- docs/SUMMARY.md | 2 + docs/extra-library/actors/README.md | 6 + docs/extra-library/actors/health.md | 463 +++++++++++++++++++++++ docs/extra-library/actors/metrics.md | 95 ++++- docs/extra-library/applications/radar.md | 321 ++++++++++++++++ 5 files changed, 879 insertions(+), 8 deletions(-) create mode 100644 docs/extra-library/actors/health.md create mode 100644 docs/extra-library/applications/radar.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index c14dd0387..d2abe37a7 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -60,11 +60,13 @@ ## extra library * [Actors](extra-library/actors/README.md) + * [Health](extra-library/actors/health.md) * [Leader](extra-library/actors/leader.md) * [Metrics](extra-library/actors/metrics.md) * [Applications](extra-library/applications/README.md) * [Observer](extra-library/applications/observer.md) * [MCP](extra-library/applications/mcp.md) + * [Radar](extra-library/applications/radar.md) * [Meta-Processes](extra-library/meta-processes/README.md) * [WebSocket](extra-library/meta-processes/websocket.md) * [SSE](extra-library/meta-processes/sse.md) diff --git a/docs/extra-library/actors/README.md b/docs/extra-library/actors/README.md index b92ead6f2..0db998c11 100644 --- a/docs/extra-library/actors/README.md +++ b/docs/extra-library/actors/README.md @@ -2,6 +2,12 @@ An extra library of actors implementations not included in the standard Ergo Framework library. This library contains packages with a narrow specialization. It also includes packages with external dependencies, as Ergo Framework adheres to a "zero dependency" policy. +## [Health](health.md) + +Kubernetes health probe actor that serves `/health/live`, `/health/ready`, and `/health/startup` endpoints. Actors register named signals with probe type and optional heartbeat timeout. When a signal goes down, the corresponding probe endpoint returns 503. + +**Use cases:** Kubernetes liveness/readiness/startup probes, container orchestration integration, dependency health tracking, graceful degradation. + ## [Leader](leader.md) Distributed leader election actor implementing Raft-inspired consensus algorithm. Provides coordination primitives for building systems that require single leader selection across a cluster. diff --git a/docs/extra-library/actors/health.md b/docs/extra-library/actors/health.md new file mode 100644 index 000000000..be23f9fb6 --- /dev/null +++ b/docs/extra-library/actors/health.md @@ -0,0 +1,463 @@ +# Health + +The health actor provides Kubernetes-compatible health probe endpoints for Ergo applications. Instead of each application building its own HTTP health check logic, the health actor centralizes probe management into a single process that serves `/health/live`, `/health/ready`, and `/health/startup` endpoints. + +Actors register named signals with the health actor, optionally sending periodic heartbeats. The health actor aggregates signal states and serves HTTP responses that Kubernetes (or any other orchestrator) can use to determine whether to restart a pod, route traffic to it, or wait for it to finish starting. + +## The Problem + +Kubernetes uses three types of probes to manage pod lifecycle: + +**Liveness** -- Is the application alive? A failing liveness probe causes Kubernetes to restart the pod. Use this for detecting deadlocks, infinite loops, or corrupted state that prevents the application from functioning. + +**Readiness** -- Can the application serve traffic? A failing readiness probe removes the pod from service endpoints. Use this for temporary conditions like database connection loss, cache warming, or downstream dependency outages where restarting would not help. + +**Startup** -- Has the application finished initializing? A failing startup probe prevents liveness and readiness checks from running. Use this for slow-starting applications that need time to load data, run migrations, or establish connections before health checks begin. + +In traditional applications, you implement these probes as HTTP handlers that check internal state. In actor systems, the "state" is distributed across many processes. A database connection actor, a cache warmer, and a message queue consumer each know their own status, but no single actor knows the overall health. + +The health actor solves this by accepting signal registrations from any actor in the system. Each actor reports its own status, and the health actor aggregates these signals into per-probe HTTP responses. + +## How It Works + +The health actor follows a registration and heartbeat pattern: + +1. **Actors register signals** -- Each actor that contributes to health sends a `MessageRegister` to the health actor, specifying a signal name, which probes it affects, and an optional heartbeat timeout. + +2. **The health actor monitors registrants** -- When a signal is registered, the health actor monitors the registering process. If that process terminates, all its signals are automatically marked as down. + +3. **Actors send heartbeats** -- For signals with a timeout, the registering actor periodically sends `MessageHeartbeat`. If the heartbeat interval exceeds the timeout, the health actor marks the signal as down. + +4. **HTTP handlers read atomic state** -- The HTTP handlers read pre-built JSON responses from atomic values. The actor goroutine rebuilds these atomic values after every state change. No mutexes or channels are involved in serving HTTP requests. + +```mermaid +sequenceDiagram + participant DB as DB Actor + participant H as Health Actor + participant K as Kubernetes + + DB->>H: MessageRegister{Signal: "db", Probe: Liveness|Readiness, Timeout: 5s} + Note over H: Monitor DB Actor
Signal "db" = up + + loop Every 2 seconds + DB->>H: MessageHeartbeat{Signal: "db"} + end + + K->>H: GET /health/live + H->>K: 200 {"status":"healthy","signals":[{"signal":"db","status":"up","timeout":"5s"}]} + + Note over DB: Process crashes + Note over H: MessageDownPID received
Signal "db" = down + + K->>H: GET /health/live + H->>K: 503 {"status":"unhealthy","signals":[{"signal":"db","status":"down","timeout":"5s"}]} + + Note over K: Restart pod +``` + +## ActorBehavior Interface + +The health actor extends `gen.ProcessBehavior` with a specialized interface: + +```go +type ActorBehavior interface { + gen.ProcessBehavior + + Init(args ...any) (Options, error) + HandleMessage(from gen.PID, message any) error + HandleCall(from gen.PID, ref gen.Ref, message any) (any, error) + HandleInspect(from gen.PID, item ...string) map[string]string + HandleSignalDown(signal gen.Atom) error + HandleSignalUp(signal gen.Atom) error + Terminate(reason error) +} +``` + +All callbacks have default (no-op) implementations. You only override what you need. + +`HandleSignalDown` is called when a signal transitions from up to down -- due to heartbeat timeout, process termination, or explicit `MessageSignalDown`. Use this for alerting, logging, or triggering recovery actions. + +`HandleSignalUp` is called when a signal transitions from down to up -- via heartbeat recovery or explicit `MessageSignalUp`. Use this to log recovery events or update external systems. + +## Basic Usage + +Spawn the health actor and register it with a name so other actors can find it: + +```go +package main + +import ( + "ergo.services/actor/health" + "ergo.services/ergo" + "ergo.services/ergo/gen" +) + +func main() { + node, _ := ergo.StartNode("mynode@localhost", gen.NodeOptions{}) + defer node.Stop() + + node.SpawnRegister(gen.Atom("health"), health.Factory, gen.ProcessOptions{}, + health.Options{Port: 8080}) + + // Endpoints: + // http://localhost:8080/health/live + // http://localhost:8080/health/ready + // http://localhost:8080/health/startup + node.Wait() +} +``` + +Default configuration: +- **Host**: `localhost` +- **Port**: `3000` +- **Path**: `/health` +- **CheckInterval**: `1 second` + +With no signals registered, all three endpoints return 200 with `{"status":"healthy"}`. This means a freshly started health actor does not block deployment. Signals opt in to health checking -- only registered signals can cause a probe to fail. + +## Configuration + +```go +options := health.Options{ + Host: "0.0.0.0", // Listen on all interfaces + Port: 8080, // HTTP port + Path: "/health", // Path prefix (default: "/health") + CheckInterval: 2 * time.Second, // Heartbeat check interval +} +``` + +**Host** determines which network interface the HTTP server binds to. Use `"0.0.0.0"` for production/containerized environments. + +**Port** should not conflict with other services on the same pod. + +**Path** sets the prefix for health endpoints. Endpoints are registered as `Path+"/live"`, `Path+"/ready"`, `Path+"/startup"`. Change this when the default conflicts with your routing or when deploying behind a reverse proxy. For example, with `Path: "/k8s"` the endpoints become `/k8s/live`, `/k8s/ready`, `/k8s/startup`. + +**CheckInterval** controls how frequently the actor checks for expired heartbeats. The actor sends itself a timer message at this interval and iterates over all signals with a non-zero timeout, marking expired ones as down. Shorter intervals detect failures faster but increase message processing overhead. For most applications, 1-2 seconds provides a good balance. + +**Mux** accepts an external `*http.ServeMux`. When provided, the health actor registers its handlers on this mux and skips starting its own HTTP server. This is useful when you want to serve health endpoints alongside other HTTP handlers on a single port -- for example, combining with the [Metrics](metrics.md) actor. + +```go +mux := http.NewServeMux() + +healthOpts := health.Options{Mux: mux} +node.SpawnRegister("health", health.Factory, gen.ProcessOptions{}, healthOpts) + +metricsOpts := metrics.Options{Mux: mux} +node.Spawn(metrics.Factory, gen.ProcessOptions{}, metricsOpts) + +// Serve the shared mux yourself +``` + +When `Mux` is set, `Host` and `Port` are ignored. + +## Signal Registration + +### Probe Types + +Each signal specifies which probes it affects using a bitmask: + +```go +const ( + ProbeLiveness Probe = 1 << iota // 1 -- /health/live + ProbeReadiness // 2 -- /health/ready + ProbeStartup // 4 -- /health/startup +) +``` + +Combine probes with bitwise OR. A database connection that affects both liveness and readiness: + +```go +health.Register(w, gen.Atom("health"), "db", + health.ProbeLiveness|health.ProbeReadiness, 5*time.Second) +``` + +A migration signal that only affects startup: + +```go +health.Register(w, gen.Atom("health"), "migrations", + health.ProbeStartup, 0) +``` + +When `Probe` is 0, it defaults to `ProbeLiveness`. + +### Helper Functions + +The package provides convenience functions that send the appropriate messages: + +```go +// Register a signal +health.Register(process, to, signal, probe, timeout) + +// Remove a signal +health.Unregister(process, to, signal) + +// Send heartbeat +health.Heartbeat(process, to, signal) + +// Manual control +health.SignalUp(process, to, signal) +health.SignalDown(process, to, signal) +``` + +The `to` parameter accepts anything that `gen.Process.Send()` accepts -- a `gen.Atom` name, `gen.PID`, `gen.ProcessID`, or `gen.Alias`. + +### Message Types + +If you prefer sending messages directly instead of using helpers: + +| Message | Description | +|---------|-------------| +| `MessageRegister` | Register a signal. Fields: `Signal gen.Atom`, `Probe Probe`, `Timeout time.Duration` | +| `MessageUnregister` | Remove a signal. Fields: `Signal gen.Atom` | +| `MessageHeartbeat` | Update heartbeat timestamp. Fields: `Signal gen.Atom` | +| `MessageSignalUp` | Mark a signal as up. Fields: `Signal gen.Atom` | +| `MessageSignalDown` | Mark a signal as down. Fields: `Signal gen.Atom` | + +All message types are registered with EDF for network transparency. Actors on remote nodes can register signals with a health actor on any node in the cluster. + +## Heartbeat Pattern + +The heartbeat pattern is the primary mechanism for detecting failures in long-running dependencies. The actor that owns a resource (database, external API, message queue) knows best whether the resource is healthy. It registers a signal with a timeout and sends periodic heartbeats as long as the resource is available. + +```go +type DBWorker struct { + act.Actor + heartbeatTimer gen.CancelFunc +} + +type messageHeartbeatTick struct{} + +func (w *DBWorker) Init(args ...any) error { + // Register with 5-second heartbeat timeout + health.Register(w, gen.Atom("health"), "db", + health.ProbeLiveness|health.ProbeReadiness, 5*time.Second) + + // Send heartbeat every 2 seconds (well within the 5s timeout) + w.heartbeatTimer, _ = w.SendAfter(w.PID(), messageHeartbeatTick{}, 2*time.Second) + return nil +} + +func (w *DBWorker) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageHeartbeatTick: + health.Heartbeat(w, gen.Atom("health"), "db") + w.heartbeatTimer, _ = w.SendAfter(w.PID(), messageHeartbeatTick{}, 2*time.Second) + } + return nil +} + +func (w *DBWorker) Terminate(reason error) { + if w.heartbeatTimer != nil { + w.heartbeatTimer() + } +} +``` + +Choose the heartbeat interval to be at least 2x shorter than the timeout. This provides one missed heartbeat as a safety margin before the signal is marked as down. + +When the actor crashes, the health actor receives a `gen.MessageDownPID` (because it monitors the registrant) and marks all signals from that process as down. Heartbeat timeout is a secondary detection mechanism for situations where the process is alive but the resource it manages is not -- for example, a database connection pool actor that is running but has lost all connections. + +## HTTP Endpoints + +| Path | Probe | Default (no signals) | +|------|-------|---------------------| +| `{Path}/live` | ProbeLiveness | 200 healthy | +| `{Path}/ready` | ProbeReadiness | 200 healthy | +| `{Path}/startup` | ProbeStartup | 200 healthy | + +Each endpoint evaluates only signals registered for that specific probe. A signal registered for `ProbeLiveness` only does not affect `/health/ready` or `/health/startup`. + +**200 OK** -- all signals for this probe are up, or no signals are registered. + +**503 Service Unavailable** -- at least one signal for this probe is down. + +### Response Format + +Healthy response with signals: + +```json +{"status":"healthy","signals":[{"signal":"db","status":"up","timeout":"5s"}]} +``` + +Unhealthy response: + +```json +{"status":"unhealthy","signals":[{"signal":"db","status":"down","timeout":"5s"},{"signal":"cache","status":"up"}]} +``` + +Healthy response with no signals (probe has no registered signals): + +```json +{"status":"healthy"} +``` + +The `timeout` field appears only for signals that have a heartbeat timeout configured. Signals without timeout omit this field. + +## Failure Detection + +The health actor detects failures through three mechanisms: + +### Process Termination + +When a process that registered signals terminates (normally or abnormally), the health actor receives `gen.MessageDownPID` through its monitor. All signals from that process are immediately marked as down. This is the fastest and most reliable detection mechanism. + +### Heartbeat Timeout + +For signals with a non-zero timeout, the health actor periodically checks whether the last heartbeat was received within the timeout window. If a heartbeat is overdue, the signal is marked as down and `HandleSignalDown` is called. + +Heartbeat timeout catches situations where the process is alive but the resource it monitors is unavailable. The process continues to run (so no `MessageDownPID` arrives) but stops sending heartbeats because the resource check fails. + +### Manual Control + +Actors can explicitly report status changes using `MessageSignalUp` and `MessageSignalDown`. Use this when you can detect failures immediately without waiting for a timeout -- for example, catching a database connection error in a callback and immediately marking the signal as down, then marking it up again when the connection is re-established. + +## Extending with Custom Behavior + +Embed `health.Actor` in your own struct to add custom behavior: + +```go +type MyHealth struct { + health.Actor +} + +func MyHealthFactory() gen.ProcessBehavior { + return &MyHealth{} +} + +func (h *MyHealth) Init(args ...any) (health.Options, error) { + return health.Options{Port: 8080}, nil +} + +func (h *MyHealth) HandleSignalDown(signal gen.Atom) error { + h.Log().Error("signal went down: %s", signal) + // Alert external monitoring, update metrics, trigger recovery + return nil +} + +func (h *MyHealth) HandleSignalUp(signal gen.Atom) error { + h.Log().Info("signal recovered: %s", signal) + return nil +} +``` + +Override `HandleMessage` to handle application-specific messages alongside health management. The health actor dispatches its own message types (`MessageRegister`, `MessageHeartbeat`, etc.) internally -- only unrecognized messages are forwarded to `HandleMessage`. + +## Kubernetes Configuration + +Configure Kubernetes probes to point to the health actor's endpoints: + +```yaml +apiVersion: v1 +kind: Pod +spec: + containers: + - name: myapp + livenessProbe: + httpGet: + path: /health/live + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /health/ready + port: 3000 + initialDelaySeconds: 5 + periodSeconds: 10 + startupProbe: + httpGet: + path: /health/startup + port: 3000 + failureThreshold: 30 + periodSeconds: 2 +``` + +Adjust `initialDelaySeconds` based on how long your application takes to start and register signals. The startup probe with `failureThreshold: 30` and `periodSeconds: 2` gives the application 60 seconds to complete initialization before Kubernetes considers it failed. + +## Common Patterns + +### Database Health + +Register liveness and readiness signals with heartbeat: + +```go +func (w *DBWorker) Init(args ...any) error { + health.Register(w, gen.Atom("health"), "postgres", + health.ProbeLiveness|health.ProbeReadiness, 10*time.Second) + + w.scheduleHeartbeat() + return nil +} + +func (w *DBWorker) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageHeartbeat: + if w.db.Ping() == nil { + health.Heartbeat(w, gen.Atom("health"), "postgres") + } + w.scheduleHeartbeat() + } + return nil +} +``` + +If `db.Ping()` fails, no heartbeat is sent, and the signal times out. The health actor marks it as down, causing Kubernetes to remove the pod from service endpoints (readiness) and eventually restart it (liveness). + +### Startup Gate + +Use the startup probe for slow initialization: + +```go +func (w *Migrator) Init(args ...any) error { + health.Register(w, gen.Atom("health"), "migrations", + health.ProbeStartup, 0) // No timeout -- manual control + + w.Send(w.PID(), messageRunMigrations{}) + return nil +} + +func (w *Migrator) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageRunMigrations: + if err := w.runMigrations(); err != nil { + health.SignalDown(w, gen.Atom("health"), "migrations") + return err + } + health.SignalUp(w, gen.Atom("health"), "migrations") + // Unregister since startup is complete + health.Unregister(w, gen.Atom("health"), "migrations") + } + return nil +} +``` + +While migrations run, the startup probe returns 503, preventing Kubernetes from running liveness and readiness checks. Once migrations complete, the signal is unregistered and the startup probe returns 200. + +### Temporary Degradation + +Use readiness-only signals for recoverable issues: + +```go +func (w *CacheWorker) HandleMessage(from gen.PID, message any) error { + switch msg := message.(type) { + case CacheConnectionLost: + health.SignalDown(w, gen.Atom("health"), "cache") + // Pod removed from service but not restarted + + case CacheConnectionRestored: + health.SignalUp(w, gen.Atom("health"), "cache") + // Pod added back to service + } + return nil +} +``` + +Register the signal for `ProbeReadiness` only. The pod stops receiving traffic during the outage but is not restarted, since the cache connection will likely recover on its own. + +## Observer Integration + +The health actor integrates with Observer via `HandleInspect()`. Inspecting the health actor shows the endpoint URL, signal count, check interval, and current status of each registered signal. + +## Radar Application + +If your node needs both health probes and Prometheus metrics, consider the [Radar](../applications/radar.md) application. It runs the health actor and metrics actor together on a single HTTP port and provides helper functions so your actors don't need to import either package directly. diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index fa9dbb873..beee7612f 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -96,6 +96,7 @@ func main() { Default configuration: - **Host**: `localhost` - **Port**: `3000` +- **Path**: `/metrics` - **CollectInterval**: `10 seconds` - **TopN**: `50` @@ -109,6 +110,7 @@ Customize the HTTP endpoint and collection frequency: options := metrics.Options{ Host: "0.0.0.0", // Listen on all interfaces Port: 9090, // Prometheus default port + Path: "/metrics", // HTTP path (default: "/metrics") CollectInterval: 5 * time.Second, // Collect every 5 seconds TopN: 50, // Top-N entries for each metric group (processes and events) } @@ -120,10 +122,31 @@ node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) **Port** should not conflict with other services. Prometheus conventionally uses `9090`, but many Ergo applications use that for other purposes. Choose a port that doesn't collide with your application's HTTP servers, Observer UI (default `9911`), or other metrics exporters. +**Path** sets the HTTP path where the Prometheus handler is registered. Default is `"/metrics"`. Change it when the default path conflicts with your application's routing or when you need metrics at a non-standard location behind a reverse proxy. + **TopN** sets how many top entries are tracked for each metric group -- mailbox depth, utilization, latency for processes, and subscribers, published, local sent, remote sent for events (default: 50). Higher values provide more visibility but increase Prometheus cardinality. Set to 0 is not supported; the minimum effective value is 1. **CollectInterval** controls how frequently the actor queries node statistics. Shorter intervals provide more granular time-series data but increase CPU usage for collection. Longer intervals reduce overhead but miss short-lived spikes. For most applications, 10-15 seconds balances responsiveness with resource usage. Prometheus typically scrapes every 15-60 seconds, so collecting more frequently than your scrape interval wastes resources. +**Mux** accepts an external `*http.ServeMux`. When provided, the metrics actor registers its handler on this mux and skips starting its own HTTP server. This is useful when you want to serve metrics alongside other HTTP handlers on a single port -- for example, combining the metrics endpoint with the [Health](health.md) actor endpoints or your own application handlers. When `Mux` is set, `Host` and `Port` are ignored. + +```go +mux := http.NewServeMux() + +// Metrics actor registers /metrics on this mux +metricsOpts := metrics.Options{ + Mux: mux, + CollectInterval: 5 * time.Second, +} +node.Spawn(metrics.Factory, gen.ProcessOptions{}, metricsOpts) + +// Health actor registers /health/* on the same mux +healthOpts := health.Options{Mux: mux} +node.SpawnRegister("health", health.Factory, gen.ProcessOptions{}, healthOpts) + +// Serve the shared mux yourself +``` + ## Base Metrics The metrics actor automatically exposes these Prometheus metrics without any configuration: @@ -292,9 +315,36 @@ All per-process metrics (latency, depth, utilization, throughput, wakeups/drains ## Custom Metrics -Extend the metrics actor by embedding `metrics.Actor`. You register custom Prometheus collectors in `Init()` and update them via `CollectMetrics()` or `HandleMessage()`. +There are three approaches to custom metrics depending on your use case: helper functions from any actor, embedding `metrics.Actor` for direct registry access, and shared mode for high-throughput scenarios. + +### Helper Functions + +Any actor on the same node can register and update custom metrics without importing `prometheus` or embedding the metrics actor. Registration is a synchronous Call (returns error on failure). Updates are asynchronous Send (fire-and-forget). + +```go +// Register metrics (sync Call, returns error) +metrics.RegisterGauge(w, "metrics_actor", "db_connections", "Active connections", []string{"pool"}) +metrics.RegisterCounter(w, "metrics_actor", "cache_ops", "Cache operations", []string{"op"}) +metrics.RegisterHistogram(w, "metrics_actor", "request_seconds", "Latency", []string{"path"}, nil) + +// Update metrics (async Send) +metrics.GaugeSet(w, "metrics_actor", "db_connections", 42, []string{"primary"}) +metrics.CounterAdd(w, "metrics_actor", "cache_ops", 1, []string{"hit"}) +metrics.HistogramObserve(w, "metrics_actor", "request_seconds", 0.023, []string{"/api"}) + +// Remove a metric (async Send) +metrics.Unregister(w, "metrics_actor", "db_connections") +``` + +The first argument is the calling process (`gen.Process`), the second is the target metrics actor (name, PID, or alias). When the registering process terminates, the metrics actor automatically unregisters all metrics it owned. + +This is the simplest approach. Use it when actors just need to report values without owning Prometheus collector objects. + +### Embedding metrics.Actor + +For direct access to the Prometheus registry, periodic collection via `CollectMetrics`, or event-driven updates via `HandleMessage`, embed `metrics.Actor`. -### Approach 1: Periodic Collection +#### Periodic Collection Implement `CollectMetrics()` to poll state at regular intervals: @@ -345,7 +395,7 @@ func (m *AppMetrics) CollectMetrics() error { Use this when metrics reflect state you need to query - current values from other actors, computed aggregates, external API calls. -### Approach 2: Event-Driven Updates +#### Event-Driven Updates Update metrics immediately when events occur: @@ -412,6 +462,33 @@ func (h *RequestHandler) HandleMessage(from gen.PID, message any) error { Use this when your application naturally produces events. Metrics update in real-time without polling. +### Shared Mode + +A single metrics actor handles all custom metric operations sequentially -- registration, updates, and unregistration pass through one mailbox. Under high throughput this becomes a bottleneck: hundreds of actors sending gauge updates or histogram observations compete for the same process, and the mailbox grows faster than callbacks can drain it. + +Shared mode solves this by separating the Prometheus registry from the actor. You create a `metrics.Shared` object that holds the registry and a thread-safe map of registered metrics. Multiple metrics actor instances share this object -- each one can serve updates independently because Prometheus collectors are safe for concurrent use. Registration still serializes through a single actor (to avoid duplicate metric names), but updates go to any worker in a pool. + +Create the shared object and pass it to all metrics actors that should share the same registry: + +```go +shared := metrics.NewShared() + +// Primary actor: owns the HTTP endpoint and base Ergo metrics +primaryOpts := metrics.Options{ + Port: 9090, + Shared: shared, +} + +// Worker actors: handle custom metric updates only (no HTTP, no base metrics) +workerOpts := metrics.Options{ + Shared: shared, +} +``` + +The primary actor starts the HTTP server and collects base Ergo metrics as usual. Worker actors skip HTTP and base collection -- they only process custom metric messages (register, update, unregister). All actors write to the same Prometheus registry through the shared object. + +This pattern works well with `act.Pool`: put worker actors behind a pool, and the pool distributes incoming metric updates across workers automatically. The `application/radar` package uses this approach internally. + ## Metric Types Prometheus defines four metric types, each suited for different use cases: @@ -598,20 +675,22 @@ The metrics actor includes built-in Observer support via `HandleInspect()`. When - Collection interval - Current values for all metrics (base + custom) -This works automatically for custom metrics - register them in `Init()` and they appear in Observer alongside base metrics. +This works automatically for custom metrics -- register them in `Init()` and they appear in Observer alongside base metrics. -If you need custom inspection behavior, override `HandleInspect()` in your implementation: +If you embed `metrics.Actor` and override `HandleInspect()`, the base inspection data (endpoint, interval, metric values) is always included. Your returned keys are merged on top, so you can add custom fields or override base values: ```go func (m *AppMetrics) HandleInspect(from gen.PID, item ...string) map[string]string { result := make(map[string]string) - - // Custom inspection logic + // Add custom fields -- these merge with base data result["status"] = "healthy" result["custom_info"] = "some value" - return result } ``` For detailed configuration options, see the `metrics.Options` struct and `ActorBehavior` interface in the package. For examples of custom metrics, see the [metrics actor repository](https://github.com/ergo-services/actor). + +## Radar Application + +If your node needs both Prometheus metrics and Kubernetes health probes, consider the [Radar](../applications/radar.md) application. It runs the metrics actor and health actor together on a single HTTP port and provides helper functions so your actors don't need to import either package directly. diff --git a/docs/extra-library/applications/radar.md b/docs/extra-library/applications/radar.md new file mode 100644 index 000000000..b2e0cc8e0 --- /dev/null +++ b/docs/extra-library/applications/radar.md @@ -0,0 +1,321 @@ +# Radar + +Running an Ergo node in production typically requires two things: health probes for Kubernetes and a Prometheus metrics endpoint. Setting them up separately means two HTTP servers on two ports, two actor packages to import, and the same wiring code repeated on every node. + +Radar bundles both into a single application on one HTTP port. Internally it runs a [Health](../actors/health.md) actor for probe endpoints, a [Metrics](../actors/metrics.md) actor for base Ergo telemetry, and a pool of metrics workers for custom metric updates -- all behind a shared mux served by one HTTP server. Actors interact with Radar through helper functions in the `radar` package without importing the underlying packages or knowing the internal actor names. + +## Adding to Your Node + +```go +import ( + "ergo.services/application/radar" + "ergo.services/ergo" + "ergo.services/ergo/gen" +) + +func main() { + node, _ := ergo.StartNode("mynode@localhost", gen.NodeOptions{ + Applications: []gen.ApplicationBehavior{ + radar.CreateApp(radar.Options{Port: 9090}), + }, + }) + + // Health: http://localhost:9090/health/live + // http://localhost:9090/health/ready + // http://localhost:9090/health/startup + // Metrics: http://localhost:9090/metrics + + node.Wait() +} +``` + +With no signals registered, all three health endpoints return 200 with `{"status":"healthy"}`. The metrics endpoint immediately serves base Ergo metrics. No additional configuration is required for a working production setup. + +## Configuration + +```go +radar.Options{ + Host: "0.0.0.0", + Port: 9090, + HealthPath: "/health", + MetricsPath: "/metrics", + HealthCheckInterval: 2 * time.Second, + MetricsCollectInterval: 15 * time.Second, + MetricsTopN: 100, + MetricsPoolSize: 5, +} +``` + +**Host** determines which network interface the HTTP server binds to. Default is `"localhost"`. Use `"0.0.0.0"` for containerized environments where probes and scraping come from outside the pod. + +**Port** sets the single HTTP port for all endpoints. Default is `9090`. Choose a port that does not conflict with your application's own listeners. + +**HealthPath** sets the URL prefix for health probe endpoints. Default is `"/health"`. The actual endpoints become `HealthPath+"/live"`, `HealthPath+"/ready"`, `HealthPath+"/startup"`. Change this when deploying behind a reverse proxy that expects a different path prefix. + +**MetricsPath** sets the URL path for the Prometheus scrape target. Default is `"/metrics"`. + +**HealthCheckInterval** controls how often the health actor checks for expired heartbeats. Default is 1 second. Shorter intervals detect failures faster but increase internal message traffic. For most applications, 1-2 seconds provides a good balance. + +**MetricsCollectInterval** sets how often base Ergo metrics are collected (processes, memory, CPU, network, events). Default is 10 seconds. Align this with your Prometheus scrape interval -- collecting more frequently than Prometheus scrapes wastes CPU; collecting less frequently means Prometheus may see stale values. + +**MetricsTopN** limits the number of entries in per-process and per-event top-N metrics tables. Default is 50. Increase this for large nodes with thousands of processes where you need broader visibility into the tail. The collection cost scales linearly with TopN. + +**MetricsPoolSize** sets the number of worker actors in the custom metrics pool. Default is 3. Under normal load, a single worker is sufficient. Increase this if many actors send frequent metric updates and you observe the metrics mailbox growing. + +## Health Probes + +Actors register signals with Radar, specifying which probes the signal affects and an optional heartbeat timeout. The health actor monitors the registering process -- if it terminates, all its signals are automatically marked as down. + +### Registering a Signal + +```go +func (w *DBWorker) Init(args ...any) error { + radar.RegisterService(w, "postgres", + radar.ProbeLiveness|radar.ProbeReadiness, 10*time.Second) + + w.scheduleHeartbeat() + return nil +} + +func (w *DBWorker) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageHeartbeat: + radar.Heartbeat(w, "postgres") + w.scheduleHeartbeat() + } + return nil +} + +func (w *DBWorker) scheduleHeartbeat() { + w.cancelHeartbeat, _ = w.SendAfter(w.PID(), messageHeartbeat{}, 3*time.Second) +} +``` + +The signal `"postgres"` participates in both liveness and readiness probes. If the heartbeat stops arriving (timeout expires) or the process terminates, Kubernetes receives a 503 on both `/health/live` and `/health/ready`. + +### Probe Types + +| Constant | Endpoint | +|----------|----------| +| `radar.ProbeLiveness` | `/health/live` | +| `radar.ProbeReadiness` | `/health/ready` | +| `radar.ProbeStartup` | `/health/startup` | + +Combine with bitwise OR. A signal registered for `ProbeLiveness|ProbeReadiness` affects both endpoints independently. + +### Manual Signal Control + +When you can detect failures immediately without waiting for a timeout: + +```go +case CacheConnectionLost: + radar.ServiceDown(w, "cache") + +case CacheConnectionRestored: + radar.ServiceUp(w, "cache") +``` + +### Helper Functions + +```go +radar.RegisterService(process, signal, probe, timeout) // sync Call +radar.UnregisterService(process, signal) // sync Call +radar.Heartbeat(process, signal) // async Send +radar.ServiceUp(process, signal) // async Send +radar.ServiceDown(process, signal) // async Send +``` + +`RegisterService` and `UnregisterService` are synchronous calls that return an error on failure. `Heartbeat`, `ServiceUp`, and `ServiceDown` are asynchronous sends (fire-and-forget). + +For a detailed explanation of the heartbeat model, failure detection mechanisms, and the HTTP response format, see the [Health](../actors/health.md) actor documentation. + +## Custom Metrics + +Actors register Prometheus metric collectors and update them through Radar's helper functions. The underlying metrics actor manages the Prometheus registry and HTTP exposition. Registration is synchronous, updates are asynchronous. + +### Registering Metrics + +```go +func (w *APIHandler) Init(args ...any) error { + radar.RegisterGauge(w, "active_connections", + "Number of active client connections", []string{"protocol"}) + + radar.RegisterCounter(w, "requests_total", + "Total HTTP requests processed", []string{"method", "status"}) + + radar.RegisterHistogram(w, "request_duration_seconds", + "Request latency distribution", []string{"method"}, + []float64{0.01, 0.05, 0.1, 0.5, 1.0, 5.0}) + + return nil +} +``` + +The `labels` parameter defines the label names for the metric. When updating, you provide label values in the same order. Pass `nil` for metrics without labels. The `buckets` parameter in `RegisterHistogram` defines histogram bucket boundaries; pass `nil` for Prometheus default buckets. + +### Updating Metrics + +```go +func (w *APIHandler) HandleMessage(from gen.PID, message any) error { + switch msg := message.(type) { + case RequestCompleted: + radar.CounterAdd(w, "requests_total", 1, + []string{msg.Method, msg.StatusCode}) + radar.HistogramObserve(w, "request_duration_seconds", + msg.Duration.Seconds(), []string{msg.Method}) + case ConnectionChange: + radar.GaugeSet(w, "active_connections", + float64(msg.Count), []string{msg.Protocol}) + } + return nil +} +``` + +Updates are distributed across the worker pool. Under high throughput, multiple actors can send updates concurrently without contending on a single actor's mailbox. + +### Automatic Cleanup + +When a process that registered metrics terminates, all its metrics are automatically unregistered from the Prometheus registry. No explicit cleanup is needed. To remove a metric while the process is still running, use `radar.UnregisterMetric(process, name)`. + +### Helper Functions + +```go +// Registration (sync Call, returns error) +radar.RegisterGauge(process, name, help, labels) +radar.RegisterCounter(process, name, help, labels) +radar.RegisterHistogram(process, name, help, labels, buckets) +radar.UnregisterMetric(process, name) + +// Updates (async Send, fire-and-forget) +radar.GaugeSet(process, name, value, labels) +radar.GaugeAdd(process, name, value, labels) +radar.CounterAdd(process, name, value, labels) +radar.HistogramObserve(process, name, value, labels) +``` + +For a detailed explanation of metric types, the Grafana dashboard, and advanced usage (embedding, shared mode), see the [Metrics](../actors/metrics.md) actor documentation. + +## Common Patterns + +### Database Connection Pool + +An actor that manages a connection pool reports both health and metrics through Radar: + +```go +func (w *DBPool) Init(args ...any) error { + // Health: liveness + readiness with heartbeat + radar.RegisterService(w, "db_pool", + radar.ProbeLiveness|radar.ProbeReadiness, 10*time.Second) + + // Metrics: connection pool gauge + radar.RegisterGauge(w, "db_pool_connections", + "Database connection pool size", []string{"state"}) + + w.scheduleCheck() + return nil +} + +func (w *DBPool) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageCheck: + if w.pool.Ping() == nil { + radar.Heartbeat(w, "db_pool") + } + radar.GaugeSet(w, "db_pool_connections", + float64(w.pool.ActiveCount()), []string{"active"}) + radar.GaugeSet(w, "db_pool_connections", + float64(w.pool.IdleCount()), []string{"idle"}) + + w.scheduleCheck() + } + return nil +} +``` + +A single periodic check updates both the health signal and connection pool metrics. If the database becomes unreachable, the heartbeat stops and Kubernetes removes the pod from service. The metrics endpoint continues to show the last known pool state until the pod restarts. + +### Startup Gate with Progress + +An actor that runs migrations uses the startup probe to prevent premature traffic, and reports progress via a gauge: + +```go +func (w *Migrator) Init(args ...any) error { + radar.RegisterService(w, "migrations", radar.ProbeStartup, 0) + radar.RegisterGauge(w, "migrations_pending", + "Number of pending migrations", nil) + + w.Send(w.PID(), messageRunMigrations{}) + return nil +} + +func (w *Migrator) HandleMessage(from gen.PID, message any) error { + switch message.(type) { + case messageRunMigrations: + pending := w.countPending() + radar.GaugeSet(w, "migrations_pending", float64(pending), nil) + + if err := w.runNext(); err != nil { + return err + } + + if w.countPending() > 0 { + w.Send(w.PID(), messageRunMigrations{}) + return nil + } + + // All done -- mark startup complete + radar.GaugeSet(w, "migrations_pending", 0, nil) + radar.ServiceUp(w, "migrations") + radar.UnregisterService(w, "migrations") + } + return nil +} +``` + +While migrations run, the startup probe returns 503, Kubernetes waits, and Prometheus shows the remaining migration count. Once complete, the startup signal is released and liveness/readiness probes take over. + +## Kubernetes Configuration + +Configure Kubernetes probes and Prometheus scraping to point at the same port: + +```yaml +apiVersion: v1 +kind: Pod +spec: + containers: + - name: myapp + livenessProbe: + httpGet: + path: /health/live + port: 9090 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /health/ready + port: 9090 + periodSeconds: 10 + startupProbe: + httpGet: + path: /health/startup + port: 9090 + failureThreshold: 30 + periodSeconds: 2 +``` + +Prometheus scrape configuration: + +```yaml +scrape_configs: + - job_name: 'ergo' + static_configs: + - targets: ['localhost:9090'] + scrape_interval: 15s +``` + +Align `scrape_interval` with `MetricsCollectInterval` in Radar options. The default collect interval is 10 seconds -- scraping more frequently than the collect interval returns identical data. + +## Relationship to Health and Metrics Actors + +Radar uses [Health](../actors/health.md) and [Metrics](../actors/metrics.md) actors internally. The helper functions in the `radar` package delegate to these actors by their internal registered names. If you need capabilities beyond what the helpers expose -- embedding the metrics actor for direct Prometheus registry access, custom health actor behavior with `HandleSignalDown` callbacks, or shared mux with additional HTTP handlers -- use the underlying actors directly. + +Radar is designed for the common case: production nodes that need standard health probes and Prometheus metrics with minimal setup. For advanced scenarios, the building blocks are available as separate packages. From 2875a5e225d77a97495ddf45af0873e6f0366e9b Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Sat, 28 Feb 2026 13:42:44 +0100 Subject: [PATCH 029/122] add log messaging metrics --- docs/extra-library/actors/metrics.md | 8 ++++++++ gen/node.go | 4 ++++ node/node.go | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index beee7612f..bd5f8772f 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -177,6 +177,12 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_events_local_sent_total` | Gauge | Cumulative number of event messages delivered to local subscribers. This reflects the actual fanout load -- a single publish with 100 subscribers produces 100 local deliveries. | | `ergo_events_remote_sent_total` | Gauge | Cumulative number of event messages sent to remote nodes. Due to shared subscription optimization, one message is sent per remote node regardless of how many subscribers that node has. See [Pub/Sub Internals](../../advanced/pub-sub-internals.md). | +### Log Metrics + +| Metric | Type | Labels | Description | +|--------|------|--------|-------------| +| `ergo_log_messages_total` | Gauge | `level` | Cumulative number of log messages by level. Labels: `trace`, `debug`, `info`, `warning`, `error`, `panic`. Counting happens once in the node's log dispatcher before fan-out to loggers, so the numbers are accurate regardless of how many loggers are registered. Use `rate()` to detect error spikes or `increase()` to compare levels over time. | + ### Network Metrics | Metric | Type | Labels | Description | @@ -554,6 +560,8 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Resources** (collapsed) - Four panels covering CPU and memory. CPU User Time and CPU System Time are normalized by core count and displayed as percentages. High user CPU means compute-bound workload; high system CPU relative to user suggests excessive I/O or syscalls. Memory (OS:used) and Memory (Runtime:alloc) show memory usage over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. +**Logging** (collapsed) - Log Messages Rate shows the rate of log messages per second broken down by level as a stacked area chart. Colors follow severity: trace and debug are gray, info is green, warning is yellow, error is red, panic is dark red. A healthy system shows mostly green (info). Spikes in warning or error indicate issues worth investigating. The legend table shows current, mean, and max rates per level. Counting happens once in the node's log dispatcher before fan-out to loggers, so the numbers are accurate regardless of how many loggers are registered. + **Network** (collapsed) - Six panels covering cluster totals, per-node breakdowns, and node-pair detail for both message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. **Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). diff --git a/gen/node.go b/gen/node.go index 4edf327cb..35c2f8647 100644 --- a/gen/node.go +++ b/gen/node.go @@ -733,6 +733,10 @@ type NodeInfo struct { // Loggers lists all registered loggers with their configuration. Loggers []LoggerInfo + // LogMessages contains cumulative log message counts by level. + // Indexed as: [0]=Trace, [1]=Debug, [2]=Info, [3]=Warning, [4]=Error, [5]=Panic + LogMessages [6]uint64 + // Cron contains cron scheduler information (jobs, schedule, next run). Cron CronInfo diff --git a/node/node.go b/node/node.go index 805e3d508..3f356c180 100644 --- a/node/node.go +++ b/node/node.go @@ -106,6 +106,8 @@ type node struct { processesSpawned uint64 processesSpawnFailed uint64 processesTerminated uint64 + + logMessages [6]uint64 // atomic: 0=trace, 1=debug, 2=info, 3=warning, 4=error, 5=panic } type eventOwner struct { @@ -686,6 +688,10 @@ func (n *node) Info() (gen.NodeInfo, error) { }) } + for i := 0; i < 6; i++ { + info.LogMessages[i] = atomic.LoadUint64(&n.logMessages[i]) + } + if n.security.ExposeEnvInfo { info.Env = n.EnvList() } else { @@ -2120,6 +2126,22 @@ func (n *node) dolog(message gen.MessageLog, loggername string) { if n.isRunning() == false { return } + + switch message.Level { + case gen.LogLevelTrace: + atomic.AddUint64(&n.logMessages[0], 1) + case gen.LogLevelDebug: + atomic.AddUint64(&n.logMessages[1], 1) + case gen.LogLevelInfo: + atomic.AddUint64(&n.logMessages[2], 1) + case gen.LogLevelWarning: + atomic.AddUint64(&n.logMessages[3], 1) + case gen.LogLevelError: + atomic.AddUint64(&n.logMessages[4], 1) + case gen.LogLevelPanic: + atomic.AddUint64(&n.logMessages[5], 1) + } + if l := n.loggers[message.Level]; l != nil { if loggername != "" { if v, found := l.Load(loggername); found { From 2308eb3e8cf3440562b215cddf9594914b4efbce Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 2 Mar 2026 12:37:07 +0100 Subject: [PATCH 030/122] update docs --- docs/extra-library/actors/health.md | 37 +++++++++++++----------- docs/extra-library/actors/metrics.md | 4 +-- docs/extra-library/applications/radar.md | 2 ++ 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/extra-library/actors/health.md b/docs/extra-library/actors/health.md index be23f9fb6..80085e828 100644 --- a/docs/extra-library/actors/health.md +++ b/docs/extra-library/actors/health.md @@ -22,7 +22,7 @@ The health actor solves this by accepting signal registrations from any actor in The health actor follows a registration and heartbeat pattern: -1. **Actors register signals** -- Each actor that contributes to health sends a `MessageRegister` to the health actor, specifying a signal name, which probes it affects, and an optional heartbeat timeout. +1. **Actors register signals** -- Each actor that contributes to health sends a `RegisterRequest` to the health actor (synchronous Call), specifying a signal name, which probes it affects, and an optional heartbeat timeout. The Call returns after the signal is registered, preventing race conditions with subsequent heartbeats. 2. **The health actor monitors registrants** -- When a signal is registered, the health actor monitors the registering process. If that process terminates, all its signals are automatically marked as down. @@ -36,7 +36,8 @@ sequenceDiagram participant H as Health Actor participant K as Kubernetes - DB->>H: MessageRegister{Signal: "db", Probe: Liveness|Readiness, Timeout: 5s} + DB->>H: RegisterRequest{Signal: "db", Probe: Liveness|Readiness, Timeout: 5s} + H->>DB: RegisterResponse{} Note over H: Monitor DB Actor
Signal "db" = up loop Every 2 seconds @@ -182,38 +183,40 @@ When `Probe` is 0, it defaults to `ProbeLiveness`. ### Helper Functions -The package provides convenience functions that send the appropriate messages: +The package provides convenience functions: ```go -// Register a signal +// Register a signal (sync Call -- blocks until registered) health.Register(process, to, signal, probe, timeout) -// Remove a signal +// Remove a signal (sync Call -- blocks until removed) health.Unregister(process, to, signal) -// Send heartbeat +// Send heartbeat (async Send) health.Heartbeat(process, to, signal) -// Manual control +// Manual control (async Send) health.SignalUp(process, to, signal) health.SignalDown(process, to, signal) ``` -The `to` parameter accepts anything that `gen.Process.Send()` accepts -- a `gen.Atom` name, `gen.PID`, `gen.ProcessID`, or `gen.Alias`. +`Register` and `Unregister` use synchronous Call to confirm the operation completed. This prevents race conditions where a heartbeat or status update arrives before the signal is registered. All other helpers use async Send. + +The `to` parameter accepts anything that identifies a process -- a `gen.Atom` name, `gen.PID`, `gen.ProcessID`, or `gen.Alias`. ### Message Types If you prefer sending messages directly instead of using helpers: -| Message | Description | -|---------|-------------| -| `MessageRegister` | Register a signal. Fields: `Signal gen.Atom`, `Probe Probe`, `Timeout time.Duration` | -| `MessageUnregister` | Remove a signal. Fields: `Signal gen.Atom` | -| `MessageHeartbeat` | Update heartbeat timestamp. Fields: `Signal gen.Atom` | -| `MessageSignalUp` | Mark a signal as up. Fields: `Signal gen.Atom` | -| `MessageSignalDown` | Mark a signal as down. Fields: `Signal gen.Atom` | +| Message | Type | Description | +|---------|------|-------------| +| `RegisterRequest` / `RegisterResponse` | sync (Call) | Register a signal. Fields: `Signal gen.Atom`, `Probe Probe`, `Timeout time.Duration` | +| `UnregisterRequest` / `UnregisterResponse` | sync (Call) | Remove a signal. Fields: `Signal gen.Atom` | +| `MessageHeartbeat` | async (Send) | Update heartbeat timestamp. Fields: `Signal gen.Atom` | +| `MessageSignalUp` | async (Send) | Mark a signal as up. Fields: `Signal gen.Atom` | +| `MessageSignalDown` | async (Send) | Mark a signal as down. Fields: `Signal gen.Atom` | -All message types are registered with EDF for network transparency. Actors on remote nodes can register signals with a health actor on any node in the cluster. +All types are registered with EDF for network transparency. Actors on remote nodes can register signals with a health actor on any node in the cluster. ## Heartbeat Pattern @@ -340,7 +343,7 @@ func (h *MyHealth) HandleSignalUp(signal gen.Atom) error { } ``` -Override `HandleMessage` to handle application-specific messages alongside health management. The health actor dispatches its own message types (`MessageRegister`, `MessageHeartbeat`, etc.) internally -- only unrecognized messages are forwarded to `HandleMessage`. +Override `HandleMessage` to handle application-specific messages alongside health management. The health actor dispatches its own types internally (`RegisterRequest`/`UnregisterRequest` via HandleCall, `MessageHeartbeat`/`MessageSignalUp`/`MessageSignalDown` via HandleMessage) -- only unrecognized messages are forwarded to your callbacks. ## Kubernetes Configuration diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index bd5f8772f..a08e4e332 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -323,6 +323,8 @@ All per-process metrics (latency, depth, utilization, throughput, wakeups/drains There are three approaches to custom metrics depending on your use case: helper functions from any actor, embedding `metrics.Actor` for direct registry access, and shared mode for high-throughput scenarios. +All custom metrics automatically receive a `node` const label set to the node name. Do not include `"node"` in your variable label names -- it will cause a "duplicate label names" registration error. + ### Helper Functions Any actor on the same node can register and update custom metrics without importing `prometheus` or embedding the metrics actor. Registration is a synchronous Call (returns error on failure). Updates are asynchronous Send (fire-and-forget). @@ -564,8 +566,6 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Network** (collapsed) - Six panels covering cluster totals, per-node breakdowns, and node-pair detail for both message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. -**Nodes Overview** - A table listing all nodes with uptime, process counts, and memory. Sorted by process count. Quickly identifies recently restarted nodes (low uptime), overloaded nodes (high process count), or unhealthy nodes (non-zero zombies). - ### Working with the Dashboard The dashboard is designed around a top-down investigation pattern. Start with the Summary row for cluster health, then drill into the relevant section based on the symptom you observe. diff --git a/docs/extra-library/applications/radar.md b/docs/extra-library/applications/radar.md index b2e0cc8e0..181c53615 100644 --- a/docs/extra-library/applications/radar.md +++ b/docs/extra-library/applications/radar.md @@ -133,6 +133,8 @@ For a detailed explanation of the heartbeat model, failure detection mechanisms, Actors register Prometheus metric collectors and update them through Radar's helper functions. The underlying metrics actor manages the Prometheus registry and HTTP exposition. Registration is synchronous, updates are asynchronous. +All custom metrics automatically receive a `node` const label set to the node name. Do not include `"node"` in your variable label names -- it will cause a "duplicate label names" registration error. + ### Registering Metrics ```go From 7dea6c0e272090ddc87ae3e3c99d8a0cddafe7e6 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 3 Mar 2026 13:18:26 +0100 Subject: [PATCH 031/122] fix simultaneous connect dead loop --- gen/default.go | 1 + gen/network.go | 13 + net/handshake/accept.go | 39 ++- net/handshake/start.go | 11 +- net/handshake/types.go | 5 + node/network.go | 131 +++++++++- .../t009_simultaneous_connect_test.go | 238 ++++++++++++++++++ 7 files changed, 423 insertions(+), 15 deletions(-) create mode 100644 testing/tests/002_distributed/t009_simultaneous_connect_test.go diff --git a/gen/default.go b/gen/default.go index 1ff3091f9..0cd3b4150 100644 --- a/gen/default.go +++ b/gen/default.go @@ -33,6 +33,7 @@ var ( EnableProxyTransit: false, EnableProxyAccept: true, EnableImportantDelivery: true, + EnableSimultaneousConnect: true, } DefaultNetworkProxyFlags = NetworkProxyFlags{ diff --git a/gen/network.go b/gen/network.go index ca3e1239d..46eccd666 100644 --- a/gen/network.go +++ b/gen/network.go @@ -389,6 +389,8 @@ type NetworkFlags struct { EnableProxyAccept bool // EnableImportantDelivery enables support 'important' flag EnableImportantDelivery bool + // EnableSimultaneousConnect enables simultaneous connect detection and resolution + EnableSimultaneousConnect bool } // we must be able to extend this structure by introducing new features. @@ -420,6 +422,9 @@ func (nf NetworkFlags) MarshalEDF(w io.Writer) error { if nf.EnableImportantDelivery == true { flags |= 64 } + if nf.EnableSimultaneousConnect == true { + flags |= 128 + } binary.BigEndian.PutUint64(buf[:], flags) w.Write(buf[:]) return nil @@ -440,6 +445,7 @@ func (nf *NetworkFlags) UnmarshalEDF(buf []byte) error { nf.EnableProxyTransit = (flags & 16) > 0 nf.EnableProxyAccept = (flags & 32) > 0 nf.EnableImportantDelivery = (flags & 64) > 0 + nf.EnableSimultaneousConnect = (flags & 128) > 0 return nil } @@ -643,6 +649,10 @@ type HandshakeOptions struct { // Communicated to peer during handshake so peer knows the limit. // Peer will reject sending messages exceeding this size. MaxMessageSize int + + // CheckPending returns true if this node has a pending outgoing + // connect to the given peer. Used for simultaneous connect detection. + CheckPending func(peer Atom) bool } type HandshakeResult struct { @@ -660,6 +670,9 @@ type HandshakeResult struct { AtomMapping map[Atom]Atom + PoolSize int + PoolDSN []string + // Tail if something is left in the buffer after the handshaking we should // pass it to the proto handler Tail []byte diff --git a/net/handshake/accept.go b/net/handshake/accept.go index 50dc95c61..fec394a4f 100644 --- a/net/handshake/accept.go +++ b/net/handshake/accept.go @@ -1,6 +1,7 @@ package handshake import ( + "crypto/hmac" "crypto/sha1" "crypto/sha256" "crypto/tls" @@ -107,8 +108,29 @@ func (h *handshake) Accept(node gen.NodeHandshake, conn net.Conn, options gen.Ha return result, fmt.Errorf("incorrect digest (accept stage 'introduce')") } + // deterministic connection ID (unconditional) + connID := generateConnectionID( + node.Name(), node.Creation(), + intro.Node, intro.Creation, + options.Cookie, + ) + + // collision detection + rejection (Erlang-style, flag-gated) + if options.Flags.EnableSimultaneousConnect == true && + intro.Flags.EnableSimultaneousConnect == true && + options.CheckPending != nil && options.CheckPending(intro.Node) { + // simultaneous connect detected + if string(node.Name()) < string(intro.Node) { + // our node name is smaller -> our outgoing wins -> reject this incoming + h.writeMessage(conn, MessageReject{Reason: "simultaneous"}) + return result, fmt.Errorf("rejected incoming from %s (simultaneous connect)", intro.Node) + } + // our node name is larger -> their outgoing wins -> accept this incoming + // our connect() will handle cleanup when it finishes + } + accept := MessageAccept{} - accept.ID = lib.RandomString(32) + accept.ID = connID accept.PoolSize = h.poolsize accept.PoolDSN = append(accept.PoolDSN, conn.LocalAddr().String()) if err := h.writeMessage(conn, accept); err != nil { @@ -149,6 +171,8 @@ func (h *handshake) Accept(node gen.NodeHandshake, conn net.Conn, options gen.Ha result.PeerMaxMessageSize = intro.MaxMessageSize result.NodeFlags = options.Flags result.NodeMaxMessageSize = options.MaxMessageSize + result.PoolSize = h.poolsize + result.PoolDSN = accept.PoolDSN result.Tail = tail custom := ConnectionOptions{ @@ -173,3 +197,16 @@ func (h *handshake) getLocalTLSFingerprint(conn net.Conn, cm gen.CertManager) [] fp := sha1.Sum(cert.Certificate[0]) return fp[:] } + +func generateConnectionID(nameA gen.Atom, creationA int64, + nameB gen.Atom, creationB int64, cookie string) string { + // canonical ordering: smaller name first + first := fmt.Sprintf("%s:%d", nameA, creationA) + second := fmt.Sprintf("%s:%d", nameB, creationB) + if string(nameA) > string(nameB) { + first, second = second, first + } + mac := hmac.New(sha256.New, []byte(cookie)) + mac.Write([]byte(first + ":" + second)) + return fmt.Sprintf("%x", mac.Sum(nil)) +} diff --git a/net/handshake/start.go b/net/handshake/start.go index d5aa15536..c53db4708 100644 --- a/net/handshake/start.go +++ b/net/handshake/start.go @@ -84,8 +84,13 @@ func (h *handshake) Start(node gen.NodeHandshake, conn net.Conn, options gen.Han return result, err } - accept, ok := v.(MessageAccept) - if ok == false { + var accept MessageAccept + switch msg := v.(type) { + case MessageAccept: + accept = msg + case MessageReject: + return result, fmt.Errorf("rejected: %s", msg.Reason) + default: return result, fmt.Errorf("malformed handshake Accept message") } @@ -117,6 +122,8 @@ func (h *handshake) Start(node gen.NodeHandshake, conn net.Conn, options gen.Han result.PeerMaxMessageSize = intro2.MaxMessageSize result.NodeFlags = options.Flags result.NodeMaxMessageSize = options.MaxMessageSize + result.PoolSize = accept.PoolSize + result.PoolDSN = accept.PoolDSN result.Tail = tail custom := ConnectionOptions{ diff --git a/net/handshake/types.go b/net/handshake/types.go index 1cc65fecc..65bbec1db 100644 --- a/net/handshake/types.go +++ b/net/handshake/types.go @@ -55,6 +55,10 @@ type MessageAccept struct { DigestCert string } +type MessageReject struct { + Reason string +} + type ConnectionOptions struct { PoolSize int PoolDSN []string @@ -74,6 +78,7 @@ func init() { MessageJoin{}, MessageIntroduce{}, MessageAccept{}, + MessageReject{}, } for _, t := range types { diff --git a/node/network.go b/node/network.go index 8a14c3438..d0c69d023 100644 --- a/node/network.go +++ b/node/network.go @@ -62,6 +62,11 @@ type network struct { enableAppStart sync.Map connections sync.Map // gen.Atom (peer name) => gen.Connection + pending sync.Map // gen.Atom (peer name) => *pendingEntry +} + +type pendingEntry struct { + ready chan struct{} // closed when connect finishes (success or failure) } func (n *network) Registrar() (gen.Registrar, error) { @@ -690,6 +695,37 @@ func (n *network) GetConnection(name gen.Atom) (gen.Connection, error) { return nil, gen.ErrNoRoute } +// acquirePending tries to become the goroutine that connects to `name`. +// If another goroutine is already connecting, waits for it to finish and +// checks the result. Retries up to 3 times if the other goroutine fails. +// Returns: (entry, nil) if acquired; (nil, nil) if connection appeared; (nil, err) on failure. +func (n *network) acquirePending(name gen.Atom) (*pendingEntry, error) { + for attempt := 0; attempt < 3; attempt++ { + entry := &pendingEntry{ready: make(chan struct{})} + actual, loaded := n.pending.LoadOrStore(name, entry) + if loaded == false { + return entry, nil // acquired the slot + } + + // another connect in progress, wait for it + pe := actual.(*pendingEntry) + select { + case <-pe.ready: + // connect finished (success or failure) + case <-time.After(5 * time.Second): + return nil, fmt.Errorf("connection to %s: pending timeout", name) + } + + // check if connection appeared + if _, ok := n.connections.Load(name); ok { + return nil, nil // connection exists + } + + // connect failed and pending was cleared, retry LoadOrStore + } + return nil, fmt.Errorf("connection to %s: 3 attempts exhausted", name) +} + func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection, error) { var dial func(network, addr string) (net.Conn, error) @@ -706,13 +742,31 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection return nil, fmt.Errorf("no proto handler for %s", route.Route.ProtoVersion) } - handshake := vhandshake.(gen.NetworkHandshake) + hs := vhandshake.(gen.NetworkHandshake) proto := vproto.(gen.NetworkProto) if route.Route.Host == "" { route.Route.Host = name.Host() } + // acquire pending slot (waits for ongoing connect, retries on failure) + entry, err := n.acquirePending(name) + if err != nil { + return nil, err + } + if entry == nil { + // connection appeared while waiting + v, ok := n.connections.Load(name) + if ok == false { + return nil, gen.ErrNoRoute + } + return v.(gen.Connection), nil + } + defer func() { + n.pending.Delete(name) + close(entry.ready) // wake ALL waiting goroutines + }() + if lib.Trace() { n.node.Log().Trace("trying to connect to %s (%s:%d, tls:%v)", name, route.Route.Host, route.Route.Port, route.Route.TLS) @@ -760,6 +814,10 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection Cookie: route.Cookie, Flags: route.Flags, MaxMessageSize: n.maxmessagesize, + CheckPending: func(peer gen.Atom) bool { + _, exists := n.pending.Load(peer) + return exists + }, } if hopts.Cookie == "" { @@ -769,9 +827,13 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection hopts.Flags = n.flags } - result, err := handshake.Start(n.node, conn, hopts) + result, err := hs.Start(n.node, conn, hopts) if err != nil { conn.Close() + // on simultaneous connect rejection, check if accept path established connection + if v, ok := n.connections.Load(name); ok { + return v.(gen.Connection), nil + } return nil, err } @@ -811,26 +873,38 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection if err != nil { return nil, nil, err } - tail, err := handshake.Join(n.node, c, id, hopts) + tail, err := hs.Join(n.node, c, id, hopts) if err != nil { return nil, nil, err } return c, tail, nil } - if c, err := n.registerConnection(result.Peer, pconn); err != nil { - if err == gen.ErrTaken { - return c, nil - } + c, err := n.registerConnection(result.Peer, pconn) + if err == nil { + pconn.Join(conn, result.ConnectionID, redial, result.Tail) + go n.serve(proto, pconn, redial) + return pconn, nil + } + + if err != gen.ErrTaken { pconn.Terminate(err) conn.Close() return nil, err } - pconn.Join(conn, result.ConnectionID, redial, result.Tail) - go n.serve(proto, pconn, redial) + // ErrTaken: another path registered first + pconn.Terminate(nil) // cleanup abandoned pconn - return pconn, nil + // with deterministic ID, join our TCP into the existing connection + if jerr := c.Join(conn, result.ConnectionID, redial, result.Tail); jerr != nil { + conn.Close() + return c, nil + } + + // expand pool (existing connection may have been registered by accept with nil redial) + go n.expandPool(c, redial, result.ConnectionID, result.PoolSize, result.PoolDSN) + return c, nil } func (n *network) serve(proto gen.NetworkProto, conn gen.Connection, redial gen.NetworkDial) { @@ -850,6 +924,24 @@ func (n *network) serve(proto gen.NetworkProto, conn gen.Connection, redial gen. conn.Terminate(err) } +func (n *network) expandPool(c gen.Connection, redial gen.NetworkDial, + connID string, poolSize int, poolDSN []string) { + if poolSize < 2 || len(poolDSN) == 0 { + return + } + for i := 1; i < poolSize; i++ { + dsn := poolDSN[i%len(poolDSN)] + nc, tail, err := redial(dsn, connID) + if err != nil { + continue + } + if err := c.Join(nc, connID, redial, tail); err != nil { + nc.Close() + return // pool full or connection terminated + } + } +} + func (n *network) connectProxy(name gen.Atom, route gen.NetworkProxyRoute) (gen.Connection, error) { if lib.Trace() { n.node.Log().Trace("trying to connect to %s (via proxy %s)", name, route.Route.Proxy) @@ -1205,6 +1297,10 @@ func (n *network) accept(a *acceptor) { Flags: a.flags, MaxMessageSize: a.max_message_size, CertManager: a.cert_manager, + CheckPending: func(peer gen.Atom) bool { + _, exists := n.pending.Load(peer) + return exists + }, } for { c, err := a.l.Accept() @@ -1280,8 +1376,19 @@ func (n *network) accept(a *acceptor) { } if _, err := n.registerConnection(result.Peer, conn); err != nil { - n.node.Log().Warning("unable to register new connection with %s: %s", result.Peer, err) - c.Close() + // connect() registered between our Load and LoadOrStore + conn.Terminate(nil) // fix: cleanup the unused connection object + + // with deterministic ID, join TCP into the existing connection + existing, ok := n.connections.Load(result.Peer) + if ok == false { + c.Close() + continue + } + ec := existing.(gen.Connection) + if jerr := ec.Join(c, result.ConnectionID, nil, result.Tail); jerr != nil { + c.Close() + } continue } conn.Join(c, result.ConnectionID, nil, result.Tail) diff --git a/testing/tests/002_distributed/t009_simultaneous_connect_test.go b/testing/tests/002_distributed/t009_simultaneous_connect_test.go new file mode 100644 index 000000000..d2c8eb405 --- /dev/null +++ b/testing/tests/002_distributed/t009_simultaneous_connect_test.go @@ -0,0 +1,238 @@ +package distributed + +import ( + "fmt" + "sync" + "testing" + "time" + + "ergo.services/ergo" + "ergo.services/ergo/gen" +) + +func TestT9SimultaneousConnect(t *testing.T) { + // Test: two nodes connect to each other at the same time. + // One side wins via connect(), the other gets its connection via accept(). + // The rejected connect() returns error, but the accept path registers the connection. + // Verify: after both goroutines complete, both nodes have exactly one connection. + options1 := gen.NodeOptions{} + options1.Network.Cookie = "simconnect" + options1.Log.DefaultLogger.Disable = true + + options2 := gen.NodeOptions{} + options2.Network.Cookie = "simconnect" + options2.Log.DefaultLogger.Disable = true + + node1, err := ergo.StartNode("distT9node1simcon@localhost", options1) + if err != nil { + t.Fatal(err) + } + defer node1.Stop() + + node2, err := ergo.StartNode("distT9node2simcon@localhost", options2) + if err != nil { + t.Fatal(err) + } + defer node2.Stop() + + // simultaneously connect from both sides + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + node1.Network().GetNode(node2.Name()) + }() + go func() { + defer wg.Done() + node2.Network().GetNode(node1.Name()) + }() + wg.Wait() + + // the accept path on the rejected side needs a moment to finish + // its handshake and register the connection + time.Sleep(300 * time.Millisecond) + + // both nodes must have exactly one connection to each other + r1, err := node1.Network().Node(node2.Name()) + if err != nil { + t.Fatalf("node1 should have connection to node2: %s", err) + } + r2, err := node2.Network().Node(node1.Name()) + if err != nil { + t.Fatalf("node2 should have connection to node1: %s", err) + } + + // verify exactly one connection per node (no duplicates) + nodes1 := node1.Network().Nodes() + nodes2 := node2.Network().Nodes() + if len(nodes1) != 1 { + t.Fatalf("node1 should have exactly 1 connection, got %d", len(nodes1)) + } + if len(nodes2) != 1 { + t.Fatalf("node2 should have exactly 1 connection, got %d", len(nodes2)) + } + + // verify connection info is consistent + r1info := r1.Info() + r2info := r2.Info() + if r1info.Node != node2.Name() { + t.Fatal("connection info mismatch on node1") + } + if r2info.Node != node1.Name() { + t.Fatal("connection info mismatch on node2") + } +} + +func TestT9SimultaneousConnectNoFlag(t *testing.T) { + // Test: one node has EnableSimultaneousConnect, the other does not. + // Should fall back to current behavior (no collision detection). + options1 := gen.NodeOptions{} + options1.Network.Cookie = "simconnect2" + options1.Log.DefaultLogger.Disable = true + + options2 := gen.NodeOptions{} + options2.Network.Cookie = "simconnect2" + options2.Log.DefaultLogger.Disable = true + options2.Network.Flags = gen.NetworkFlags{ + Enable: true, + EnableRemoteSpawn: true, + EnableRemoteApplicationStart: true, + EnableProxyAccept: true, + EnableImportantDelivery: true, + EnableSimultaneousConnect: false, // explicitly disabled + } + + node1, err := ergo.StartNode("distT9node1noflag@localhost", options1) + if err != nil { + t.Fatal(err) + } + defer node1.Stop() + + node2, err := ergo.StartNode("distT9node2noflag@localhost", options2) + if err != nil { + t.Fatal(err) + } + defer node2.Stop() + + remote1, err := node1.Network().GetNode(node2.Name()) + if err != nil { + t.Fatalf("node1 -> node2 connection failed: %s", err) + } + + time.Sleep(100 * time.Millisecond) + + remote2, err := node2.Network().Node(node1.Name()) + if err != nil { + t.Fatalf("node2 should see node1: %s", err) + } + + if remote1.Name() != node2.Name() { + t.Fatal("incorrect remote1 node name") + } + if remote2.Name() != node1.Name() { + t.Fatal("incorrect remote2 node name") + } + + r1info := remote1.Info() + if r1info.NetworkFlags.EnableSimultaneousConnect == true { + t.Fatal("node2 should not have EnableSimultaneousConnect flag") + } + + r2info := remote2.Info() + if r2info.NetworkFlags.EnableSimultaneousConnect == false { + t.Fatal("node1 should have EnableSimultaneousConnect flag") + } +} + +func TestT9SimultaneousConnectCluster(t *testing.T) { + // Test: N nodes all connect to each other simultaneously. + // Reproduces the real-world scenario where a cluster of nodes + // starts up and every node tries to reach every other node at once. + // Verify: after the storm, every pair has exactly one connection, + // no dead loops, no leaked connections. + const N = 50 // 50 nodes = 1225 pairs + + cookie := "simcluster" + nodes := make([]gen.Node, N) + + for i := 0; i < N; i++ { + opts := gen.NodeOptions{} + opts.Network.Cookie = cookie + opts.Log.DefaultLogger.Disable = true + name := gen.Atom(fmt.Sprintf("distT9cluster%03d@localhost", i)) + nd, err := ergo.StartNode(name, opts) + if err != nil { + // stop already started nodes + for j := 0; j < i; j++ { + nodes[j].Stop() + } + t.Fatalf("failed to start node %d: %s", i, err) + } + nodes[i] = nd + } + defer func() { + for _, nd := range nodes { + nd.Stop() + } + }() + + // every node connects to every other node simultaneously + var wg sync.WaitGroup + for i := 0; i < N; i++ { + for j := 0; j < N; j++ { + if i == j { + continue + } + wg.Add(1) + go func(src, dst int) { + defer wg.Done() + nodes[src].Network().GetNode(nodes[dst].Name()) + }(i, j) + } + } + wg.Wait() + + // let accept paths finish + time.Sleep(3 * time.Second) + + // retry missing connections (TCP backlog overflow under 9900 concurrent dials + // can drop some connections -- same as in a real cluster, retry resolves it) + for retry := 0; retry < 3; retry++ { + missing := 0 + for i := 0; i < N; i++ { + for j := i + 1; j < N; j++ { + if _, err := nodes[i].Network().Node(nodes[j].Name()); err != nil { + missing++ + nodes[i].Network().GetNode(nodes[j].Name()) + } + } + } + if missing == 0 { + break + } + t.Logf("retry %d: %d missing connections, retrying...", retry+1, missing) + time.Sleep(time.Second) + } + + // verify: every node sees exactly N-1 peers + for i := 0; i < N; i++ { + peers := nodes[i].Network().Nodes() + if len(peers) != N-1 { + t.Fatalf("node %d has %d connections, expected %d", i, len(peers), N-1) + } + } + + // verify: every pair has a bidirectional connection + for i := 0; i < N; i++ { + for j := i + 1; j < N; j++ { + _, err := nodes[i].Network().Node(nodes[j].Name()) + if err != nil { + t.Fatalf("node %d -> node %d: no connection: %s", i, j, err) + } + _, err = nodes[j].Network().Node(nodes[i].Name()) + if err != nil { + t.Fatalf("node %d -> node %d: no connection: %s", j, i, err) + } + } + } +} From f8efcaaf659bbf1939e47248ab3ce52241d9abc1 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 3 Mar 2026 13:49:35 +0100 Subject: [PATCH 032/122] update README.md --- CHANGELOG.md | 1 + README.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdf584dc1..86366108d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added **process init time measurement** - `InitTime` field in `ProcessShortInfo` and `ProcessInfo` records the time spent in `ProcessInit` callback (nanoseconds) * Fixed **message counters for meta processes** - meta process traffic now propagates to parent process counters, making `ProcessRangeShortInfo` aggregates balanced * Fixed **self-send message counter** - `messagesOut` now incremented for self-sends +* Fixed **simultaneous connect dead loop** - two nodes dialing each other at the same time no longer cause infinite retry loops. Deterministic connection IDs and Erlang-style collision detection (`EnableSimultaneousConnect` flag) ensure exactly one connection per pair. Fixed related connection leaks #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index a9d50f26b..412f95aef 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,8 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Fixed **self-send message counter** - `messagesOut` now incremented for self-sends (process sending to itself), consistent with other send paths +* Fixed **simultaneous connect dead loop** - two nodes dialing each other at the same time no longer cause infinite retry loops. Deterministic connection IDs and Erlang-style collision detection (`EnableSimultaneousConnect` flag) ensure exactly one connection per pair. Fixed related connection leaks + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at From 6355d19a6de8c7a4986e36f56db7023893a156b7 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 3 Mar 2026 17:07:37 +0100 Subject: [PATCH 033/122] add async acceptor handling + handshake/connection churn metrics --- docs/extra-library/actors/metrics.md | 11 +- gen/network.go | 15 +++ gen/node.go | 12 ++ gen/registrar.go | 3 + net/handshake/handshake.go | 4 + net/handshake/start.go | 9 +- node/acceptor.go | 6 + node/core.go | 65 ++++++++++- node/network.go | 160 ++++++++++++++++----------- node/node.go | 10 ++ 10 files changed, 221 insertions(+), 74 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index a08e4e332..edb9ea633 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -18,7 +18,9 @@ The metrics actor addresses this by tracking: **Memory metrics** - Heap allocation and actual memory used. Actor systems can accumulate small allocations across thousands of processes. Memory metrics help identify whether garbage collection keeps pace with allocation. -**Network metrics** - For distributed Ergo clusters, tracking bytes and messages flowing between nodes reveals network bottlenecks, routing inefficiencies, or failing connections. +**Network metrics** - For distributed Ergo clusters, tracking bytes and messages flowing between nodes reveals network bottlenecks, routing inefficiencies, or failing connections. Connection churn counters and per-acceptor handshake error rates detect network instability in static clusters where connection state should be stable between deploys. + +**Delivery error metrics** - Message delivery can fail for local reasons (target process unknown, terminated, or mailbox full) and remote reasons (connection failure). Separate counters for Send and Call errors, split by local and remote, help distinguish between overloaded processes and network problems. **Event metrics** - For pub/sub events, tracking which events have the most subscribers, which generate the most delivery load, and which are wasteful (publishing into the void or registered but unused). These reveal whether your event-driven architecture is efficient or accumulating overhead. See [Events](../../basics/events.md) for the pub/sub model and [Pub/Sub Internals](../../advanced/pub-sub-internals.md) for the shared subscription optimization that affects how delivery counters work. @@ -176,6 +178,10 @@ The metrics actor automatically exposes these Prometheus metrics without any con | `ergo_events_received_total` | Gauge | Cumulative number of events received from remote nodes. Shows incoming event traffic load. | | `ergo_events_local_sent_total` | Gauge | Cumulative number of event messages delivered to local subscribers. This reflects the actual fanout load -- a single publish with 100 subscribers produces 100 local deliveries. | | `ergo_events_remote_sent_total` | Gauge | Cumulative number of event messages sent to remote nodes. Due to shared subscription optimization, one message is sent per remote node regardless of how many subscribers that node has. See [Pub/Sub Internals](../../advanced/pub-sub-internals.md). | +| `ergo_send_errors_local_total` | Gauge | Cumulative local Send delivery errors (target process unknown, terminated, or mailbox full). Non-zero rate indicates processes sending to stale PIDs or overloaded recipients. | +| `ergo_send_errors_remote_total` | Gauge | Cumulative remote Send delivery errors (connection failure to the target node). Non-zero rate indicates network connectivity problems. | +| `ergo_call_errors_local_total` | Gauge | Cumulative local Call delivery errors (same causes as local Send errors). | +| `ergo_call_errors_remote_total` | Gauge | Cumulative remote Call delivery errors (same causes as remote Send errors). | ### Log Metrics @@ -187,6 +193,9 @@ The metrics actor automatically exposes these Prometheus metrics without any con | Metric | Type | Labels | Description | |--------|------|--------|-------------| +| `ergo_connections_established_total` | Gauge | - | Cumulative connections established. In a static cluster between deploys, `rate()` should be near zero. Sustained rate indicates connection churn or nodes restarting. | +| `ergo_connections_lost_total` | Gauge | - | Cumulative connections lost. Use with `ergo_connections_established_total` to detect network instability. | +| `ergo_acceptor_handshake_errors_total` | Gauge | `acceptor` | Cumulative handshake errors per acceptor interface. Non-zero rate indicates incoming connections with wrong protocol, authentication failures, or incompatible versions. | | `ergo_connected_nodes_total` | Gauge | - | Number of remote nodes connected. For distributed systems, this should match your expected cluster size. | | `ergo_remote_node_uptime_seconds` | Gauge | `remote_node` | Uptime of each connected remote node. Resets when the remote node restarts. | | `ergo_remote_messages_in_total` | Gauge | `remote_node` | Messages received from each remote node. Rate indicates traffic volume. | diff --git a/gen/network.go b/gen/network.go index 46eccd666..3798edbf8 100644 --- a/gen/network.go +++ b/gen/network.go @@ -610,6 +610,12 @@ type AcceptorOptions struct { // Proto overrides the default network protocol for this acceptor. // Allows mixing EDF and Erlang protocols on different ports. Proto NetworkProto + + // MaxHandshakes limits the number of simultaneous in-flight handshakes + // on this acceptor. When the limit is reached, new connections are + // rejected immediately with a "busy" reason. + // Zero (default) means unlimited. + MaxHandshakes int } // Handshake defines handshake interface @@ -622,6 +628,9 @@ type NetworkHandshake interface { Join(NodeHandshake, net.Conn, string, HandshakeOptions) ([]byte, error) // Accept accepts handshake process initiated by another side of this connection. Accept(NodeHandshake, net.Conn, HandshakeOptions) (HandshakeResult, error) + // Reject sends a rejection message to the connecting side and is used + // when the acceptor is too busy to handle a new handshake. + Reject(net.Conn, string) error // Version Version() Version } @@ -731,6 +740,12 @@ type NetworkInfo struct { // Indicates what features are enabled globally. Flags NetworkFlags + // ConnectionsEstablished is the cumulative number of connections established. + ConnectionsEstablished uint64 + + // ConnectionsLost is the cumulative number of connections lost. + ConnectionsLost uint64 + // EnabledSpawn lists processes that remote nodes are allowed to spawn. // Includes process name, behavior, and which nodes can spawn it. EnabledSpawn []NetworkSpawnInfo diff --git a/gen/node.go b/gen/node.go index 35c2f8647..dbfba85f6 100644 --- a/gen/node.go +++ b/gen/node.go @@ -758,6 +758,18 @@ type NodeInfo struct { // ProcessesTerminated is the cumulative number of terminated processes. ProcessesTerminated uint64 + // SendErrorsLocal is the cumulative number of local send delivery errors. + SendErrorsLocal uint64 + + // SendErrorsRemote is the cumulative number of remote send delivery errors. + SendErrorsRemote uint64 + + // CallErrorsLocal is the cumulative number of local call delivery errors. + CallErrorsLocal uint64 + + // CallErrorsRemote is the cumulative number of remote call delivery errors. + CallErrorsRemote uint64 + // RegisteredAliases is the total number of registered aliases. RegisteredAliases int64 diff --git a/gen/registrar.go b/gen/registrar.go index c3cd47583..86f8306a1 100644 --- a/gen/registrar.go +++ b/gen/registrar.go @@ -171,6 +171,9 @@ type AcceptorInfo struct { // ProtoVersion is the network protocol version (EDF or Erlang). ProtoVersion Version + + // HandshakeErrors is the cumulative number of failed handshakes on this acceptor. + HandshakeErrors uint64 } // RegisterRoutes contains routes to publish when registering with the service registry. diff --git a/net/handshake/handshake.go b/net/handshake/handshake.go index 9ec78a036..e8d64ed62 100644 --- a/net/handshake/handshake.go +++ b/net/handshake/handshake.go @@ -58,6 +58,10 @@ func (h *handshake) Version() gen.Version { } } +func (h *handshake) Reject(conn net.Conn, reason string) error { + return h.writeMessage(conn, MessageReject{Reason: reason}) +} + func (h *handshake) writeMessage(conn net.Conn, message any) error { buf := lib.TakeBuffer() defer lib.ReleaseBuffer(buf) diff --git a/net/handshake/start.go b/net/handshake/start.go index c53db4708..65ef37233 100644 --- a/net/handshake/start.go +++ b/net/handshake/start.go @@ -37,8 +37,13 @@ func (h *handshake) Start(node gen.NodeHandshake, conn net.Conn, options gen.Han return result, err } - hello2, ok := v.(MessageHello) - if ok == false { + var hello2 MessageHello + switch msg := v.(type) { + case MessageReject: + return result, fmt.Errorf("rejected: %s", msg.Reason) + case MessageHello: + hello2 = msg + default: return result, fmt.Errorf("malformed handshake Hello message") } hash = sha256.New() diff --git a/node/acceptor.go b/node/acceptor.go index 44203a359..63002ecd5 100644 --- a/node/acceptor.go +++ b/node/acceptor.go @@ -2,6 +2,7 @@ package node import ( "net" + "sync/atomic" "ergo.services/ergo/gen" ) @@ -24,6 +25,10 @@ type acceptor struct { proto gen.NetworkProto atom_mapping map[gen.Atom]gen.Atom + + handshaking atomic.Int32 // current number of in-flight handshakes + maxHandshakes int32 // 0 = unlimited + handshakeErrors atomic.Uint64 // cumulative handshake failures } // gen.Acceptor interface implementation @@ -76,5 +81,6 @@ func (a *acceptor) Info() gen.AcceptorInfo { info.RegistrarServer = regInfo.Server } info.RegistrarVersion = regInfo.Version + info.HandshakeErrors = a.handshakeErrors.Load() return info } diff --git a/node/core.go b/node/core.go index 4b8857a51..8faa01af0 100644 --- a/node/core.go +++ b/node/core.go @@ -25,19 +25,26 @@ func (n *node) RouteSendPID(from gen.PID, to gen.PID, options gen.MessageOptions // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) return err } - return connection.SendPID(from, to, options, message) + if err := connection.SendPID(from, to, options, message); err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) + return err + } + return nil } // local value, found := n.processes.Load(to) if found == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -58,10 +65,12 @@ func (n *node) RouteSendPID(from gen.PID, to gen.PID, options gen.MessageOptions if ok := queue.Push(qm); ok == false { if p.fallback.Enable == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } if p.fallback.Name == p.name { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } @@ -97,18 +106,25 @@ func (n *node) RouteSendProcessID(from gen.PID, to gen.ProcessID, options gen.Me // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) + return err + } + if err := connection.SendProcessID(from, to, options, message); err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) return err } - return connection.SendProcessID(from, to, options, message) + return nil } value, found := n.names.Load(to.Name) if found == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -129,10 +145,12 @@ func (n *node) RouteSendProcessID(from gen.PID, to gen.ProcessID, options gen.Me if ok := queue.Push(qm); ok == false { if p.fallback.Enable == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } if p.fallback.Name == p.name { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } @@ -165,18 +183,25 @@ func (n *node) RouteSendAlias(from gen.PID, to gen.Alias, options gen.MessageOpt // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) + return err + } + if err := connection.SendAlias(from, to, options, message); err != nil { + atomic.AddUint64(&n.sendErrorsRemote, 1) return err } - return connection.SendAlias(from, to, options, message) + return nil } value, found := n.aliases.Load(to) if found == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -190,6 +215,7 @@ func (n *node) RouteSendAlias(from gen.PID, to gen.Alias, options gen.MessageOpt if value, found := p.metas.Load(to); found { m := value.(*meta) if ok := m.main.Push(qm); ok == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrMetaMailboxFull } atomic.AddUint64(&m.messagesIn, 1) @@ -209,10 +235,12 @@ func (n *node) RouteSendAlias(from gen.PID, to gen.Alias, options gen.MessageOpt if ok := queue.Push(qm); ok == false { if p.fallback.Enable == false { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } if p.fallback.Name == p.name { + atomic.AddUint64(&n.sendErrorsLocal, 1) return gen.ErrProcessMailboxFull } @@ -407,19 +435,26 @@ func (n *node) RouteCallPID(from gen.PID, to gen.PID, options gen.MessageOptions // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) return err } - return connection.CallPID(from, to, options, message) + if err := connection.CallPID(from, to, options, message); err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) + return err + } + return nil } // local value, found := n.processes.Load(to) if found == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -439,6 +474,7 @@ func (n *node) RouteCallPID(from gen.PID, to gen.PID, options gen.MessageOptions qm.Message = message if ok := queue.Push(qm); ok == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessMailboxFull } atomic.AddUint64(&p.messagesIn, 1) @@ -460,17 +496,24 @@ func (n *node) RouteCallProcessID(from gen.PID, to gen.ProcessID, options gen.Me // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) + return err + } + if err := connection.CallProcessID(from, to, options, message); err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) return err } - return connection.CallProcessID(from, to, options, message) + return nil } value, found := n.names.Load(to.Name) if found == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -491,6 +534,7 @@ func (n *node) RouteCallProcessID(from gen.PID, to gen.ProcessID, options gen.Me qm.Message = message if ok := queue.Push(qm); ok == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessMailboxFull } atomic.AddUint64(&p.messagesIn, 1) @@ -513,17 +557,24 @@ func (n *node) RouteCallAlias(from gen.PID, to gen.Alias, options gen.MessageOpt // remote connection, err := n.network.GetConnection(to.Node) if err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) + return err + } + if err := connection.CallAlias(from, to, options, message); err != nil { + atomic.AddUint64(&n.callErrorsRemote, 1) return err } - return connection.CallAlias(from, to, options, message) + return nil } value, found := n.aliases.Load(to) if found == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessUnknown } p := value.(*process) if alive := p.isAlive(); alive == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessTerminated } @@ -538,6 +589,7 @@ func (n *node) RouteCallAlias(from gen.PID, to gen.Alias, options gen.MessageOpt if value, found := p.metas.Load(to); found { m := value.(*meta) if ok := m.main.Push(qm); ok == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrMetaMailboxFull } atomic.AddUint64(&m.messagesIn, 1) @@ -555,6 +607,7 @@ func (n *node) RouteCallAlias(from gen.PID, to gen.Alias, options gen.MessageOpt queue = p.mailbox.Main } if ok := queue.Push(qm); ok == false { + atomic.AddUint64(&n.callErrorsLocal, 1) return gen.ErrProcessMailboxFull } atomic.AddUint64(&p.messagesIn, 1) diff --git a/node/network.go b/node/network.go index d0c69d023..aaf1b04bb 100644 --- a/node/network.go +++ b/node/network.go @@ -63,6 +63,9 @@ type network struct { connections sync.Map // gen.Atom (peer name) => gen.Connection pending sync.Map // gen.Atom (peer name) => *pendingEntry + + connectionsEstablished atomic.Uint64 + connectionsLost atomic.Uint64 } type pendingEntry struct { @@ -496,6 +499,9 @@ func (n *network) Info() (gen.NetworkInfo, error) { info.Flags = n.flags + info.ConnectionsEstablished = n.connectionsEstablished.Load() + info.ConnectionsLost = n.connectionsLost.Load() + info.EnabledSpawn = n.listEnabledSpawn() info.EnabledApplicationStart = n.listEnabledApplicationStart() @@ -1224,6 +1230,7 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { atom_mapping: make(map[gen.Atom]gen.Atom), route_host: a.RouteHost, route_port: a.RoutePort, + maxHandshakes: int32(a.MaxHandshakes), } if a.Cookie == "" { acceptor.cookie = n.cookie @@ -1292,8 +1299,13 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { } func (n *network) accept(a *acceptor) { + cookie := a.cookie + if cookie == "" { + cookie = n.cookie + } + hopts := gen.HandshakeOptions{ - Cookie: a.cookie, + Cookie: cookie, Flags: a.flags, MaxMessageSize: a.max_message_size, CertManager: a.cert_manager, @@ -1316,90 +1328,107 @@ func (n *network) accept(a *acceptor) { n.node.Log().Trace("accepted new TCP-connection from %s", c.RemoteAddr().String()) } - if hopts.Cookie == "" { - hopts.Cookie = n.cookie - } - - result, err := a.handshake.Accept(n.node, c, hopts) - if err != nil { - if err != io.EOF { - n.node.Log().Warning("unable to handshake with %s: %s", c.RemoteAddr().String(), err) - } + // check concurrency limit + if a.maxHandshakes > 0 && a.handshaking.Add(1) > a.maxHandshakes { + a.handshaking.Add(-1) + c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) + a.handshake.Reject(c, "busy") c.Close() continue } - if result.Peer == "" { - n.node.Log().Warning("%s is not introduced itself, close connection", c.RemoteAddr().String()) - c.Close() - continue - } + go func() { + if a.maxHandshakes > 0 { + defer a.handshaking.Add(-1) + } + n.handleAccepted(a, c, hopts) + }() + } +} - // update atom mapping: a.atom_mapping + result.AtomMapping - mapping := make(map[gen.Atom]gen.Atom) - for k, v := range a.atom_mapping { - mapping[k] = v - } - for k, v := range result.AtomMapping { - mapping[k] = v +func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOptions) { + result, err := a.handshake.Accept(n.node, c, hopts) + if err != nil { + if err != io.EOF { + n.node.Log().Warning("unable to handshake with %s: %s", c.RemoteAddr().String(), err) } - result.AtomMapping = mapping + a.handshakeErrors.Add(1) + c.Close() + return + } - // check if we already have connection with this node - if v, exist := n.connections.Load(result.Peer); exist { - conn := v.(gen.Connection) - if err := conn.Join(c, result.ConnectionID, nil, result.Tail); err != nil { - if err == gen.ErrUnsupported { - n.node.Log().Warning("unable to accept connection with %s (join is not supported)", - result.Peer) - } else { - n.node.Log().Trace("unable to join %s to the existing connection with %s: %s", - c.RemoteAddr(), result.Peer, err) - } - c.Close() - } - continue - } + if result.Peer == "" { + n.node.Log().Warning("%s is not introduced itself, close connection", c.RemoteAddr().String()) + a.handshakeErrors.Add(1) + c.Close() + return + } - log := createLog(n.node.Log().Level(), n.node.dolog) - logSource := gen.MessageLogNetwork{ - Node: n.node.name, - Peer: result.Peer, - Creation: result.PeerCreation, - } - log.setSource(logSource) - conn, err := a.proto.NewConnection(n.node, result, log) - if err != nil { - n.node.Log().Warning("unable to create new connection: %s", err) + // update atom mapping: a.atom_mapping + result.AtomMapping + mapping := make(map[gen.Atom]gen.Atom) + for k, v := range a.atom_mapping { + mapping[k] = v + } + for k, v := range result.AtomMapping { + mapping[k] = v + } + result.AtomMapping = mapping + + // check if we already have connection with this node + if v, exist := n.connections.Load(result.Peer); exist { + conn := v.(gen.Connection) + if err := conn.Join(c, result.ConnectionID, nil, result.Tail); err != nil { + if err == gen.ErrUnsupported { + n.node.Log().Warning("unable to accept connection with %s (join is not supported)", + result.Peer) + } else { + n.node.Log().Trace("unable to join %s to the existing connection with %s: %s", + c.RemoteAddr(), result.Peer, err) + } c.Close() - continue } + return + } + + log := createLog(n.node.Log().Level(), n.node.dolog) + logSource := gen.MessageLogNetwork{ + Node: n.node.name, + Peer: result.Peer, + Creation: result.PeerCreation, + } + log.setSource(logSource) + conn, err := a.proto.NewConnection(n.node, result, log) + if err != nil { + n.node.Log().Warning("unable to create new connection: %s", err) + c.Close() + return + } - if _, err := n.registerConnection(result.Peer, conn); err != nil { - // connect() registered between our Load and LoadOrStore - conn.Terminate(nil) // fix: cleanup the unused connection object + if _, err := n.registerConnection(result.Peer, conn); err != nil { + // connect() registered between our Load and LoadOrStore + conn.Terminate(nil) // fix: cleanup the unused connection object - // with deterministic ID, join TCP into the existing connection - existing, ok := n.connections.Load(result.Peer) - if ok == false { - c.Close() - continue - } - ec := existing.(gen.Connection) - if jerr := ec.Join(c, result.ConnectionID, nil, result.Tail); jerr != nil { - c.Close() - } - continue + // with deterministic ID, join TCP into the existing connection + existing, ok := n.connections.Load(result.Peer) + if ok == false { + c.Close() + return } - conn.Join(c, result.ConnectionID, nil, result.Tail) - go n.serve(a.proto, conn, nil) + ec := existing.(gen.Connection) + if jerr := ec.Join(c, result.ConnectionID, nil, result.Tail); jerr != nil { + c.Close() + } + return } + conn.Join(c, result.ConnectionID, nil, result.Tail) + go n.serve(a.proto, conn, nil) } func (n *network) registerConnection(name gen.Atom, conn gen.Connection) (gen.Connection, error) { if v, exist := n.connections.LoadOrStore(name, conn); exist { return v.(gen.Connection), gen.ErrTaken } + n.connectionsEstablished.Add(1) n.node.log.Info("new connection with %s (%s)", name, name.CRC32()) // TODO create event gen.MessageNetworkEvent return conn, nil @@ -1407,6 +1436,7 @@ func (n *network) registerConnection(name gen.Atom, conn gen.Connection) (gen.Co func (n *network) unregisterConnection(name gen.Atom, reason error) { n.connections.Delete(name) + n.connectionsLost.Add(1) if reason != nil { n.node.log.Info("connection with %s (%s) terminated with reason: %s", name, name.CRC32(), reason) } else { diff --git a/node/node.go b/node/node.go index 3f356c180..08bc8457e 100644 --- a/node/node.go +++ b/node/node.go @@ -107,6 +107,11 @@ type node struct { processesSpawnFailed uint64 processesTerminated uint64 + sendErrorsLocal uint64 + sendErrorsRemote uint64 + callErrorsLocal uint64 + callErrorsRemote uint64 + logMessages [6]uint64 // atomic: 0=trace, 1=debug, 2=info, 3=warning, 4=error, 5=panic } @@ -716,6 +721,11 @@ func (n *node) Info() (gen.NodeInfo, error) { info.ProcessesSpawnFailed = atomic.LoadUint64(&n.processesSpawnFailed) info.ProcessesTerminated = atomic.LoadUint64(&n.processesTerminated) + info.SendErrorsLocal = atomic.LoadUint64(&n.sendErrorsLocal) + info.SendErrorsRemote = atomic.LoadUint64(&n.sendErrorsRemote) + info.CallErrorsLocal = atomic.LoadUint64(&n.callErrorsLocal) + info.CallErrorsRemote = atomic.LoadUint64(&n.callErrorsRemote) + n.names.Range(func(_, _ any) bool { info.RegisteredNames++ return true From b8709d7554427cd8684d9c35dd73a7c4202d809e Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 3 Mar 2026 17:48:00 +0100 Subject: [PATCH 034/122] update docs --- docs/extra-library/actors/metrics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index edb9ea633..efc4f8acc 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -565,7 +565,7 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with four lines: Published (local producer publish rate), Received (events arriving from remote nodes), Local Delivered (actual fanout to local subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. -**Process Activity** (collapsed) - Ten panels organized by topic: message throughput, drains, then process utilization. Message Throughput (Cluster Total) and Message Throughput per Node show inbound, outbound, and wakeup rates -- the gap between message rate and wakeup rate reveals drain effect (processes batching under load). Top Processes by Messages In/Out tables identify which actors handle the most traffic. Drains per Node timeseries shows per-node drain ratio over time (`rate(messages_in) / rate(wakeups)`), and Top Processes by Drains table identifies specific actors with the highest drain -- these are the processes that handle the most messages per wakeup cycle. Drain ratio complements utilization: two processes at 80% utilization may have drain ~1 (slow callbacks) or drain ~100 (fast callbacks, high volume) -- different problems needing different solutions. Utilization Distribution, Max Utilization per Node, Actor Running Time per Node, and Top Processes by Utilization cover compute load analysis. +**Process Activity** (collapsed) - Twelve panels organized by topic: message throughput, delivery errors, drains, then process utilization. Message Throughput (Cluster Total) and Message Throughput per Node show inbound, outbound, and wakeup rates -- the gap between message rate and wakeup rate reveals drain effect (processes batching under load). Top Processes by Messages In/Out tables identify which actors handle the most traffic. Delivery Errors (Cluster Total) shows cluster-wide rate of Send and Call failures split by local (process unknown, terminated, mailbox full) and remote (connection failure); Delivery Errors per Node breaks the same data down per node to identify which nodes have the most failures. Drains per Node timeseries shows per-node drain ratio over time (`rate(messages_in) / rate(wakeups)`), and Top Processes by Drains table identifies specific actors with the highest drain -- these are the processes that handle the most messages per wakeup cycle. Drain ratio complements utilization: two processes at 80% utilization may have drain ~1 (slow callbacks) or drain ~100 (fast callbacks, high volume) -- different problems needing different solutions. Utilization Distribution, Max Utilization per Node, Actor Running Time per Node, and Top Processes by Utilization cover compute load analysis. **Processes** (collapsed) - Six panels showing per-node process counts (total and running), lifecycle rates (spawn rate with failures in red, termination rate), and initialization performance (init time bar gauge per node, top processes by init time). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. High init times indicate heavy initialization logic or blocking operations in ProcessInit. @@ -573,7 +573,7 @@ The dashboard organizes metrics into logical groups arranged from high-level ove **Logging** (collapsed) - Log Messages Rate shows the rate of log messages per second broken down by level as a stacked area chart. Colors follow severity: trace and debug are gray, info is green, warning is yellow, error is red, panic is dark red. A healthy system shows mostly green (info). Spikes in warning or error indicate issues worth investigating. The legend table shows current, mean, and max rates per level. Counting happens once in the node's log dispatcher before fan-out to loggers, so the numbers are accurate regardless of how many loggers are registered. -**Network** (collapsed) - Six panels covering cluster totals, per-node breakdowns, and node-pair detail for both message rates and byte rates. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. +**Network** (collapsed) - Eight panels covering cluster totals, per-node breakdowns, node-pair detail for both message rates and byte rates, and connection health. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. Connected Nodes is a bar gauge showing connected remote nodes per node with color thresholds: red (0, isolated), orange (1, degraded), yellow (2, partial), green (3+, healthy). Connection Events shows per-node rates of connection established (green), lost (red), and handshake errors (orange) on a single chart -- in a stable cluster all three are zero. ### Working with the Dashboard From 83fdba3bc360fbadb74858df32888d282a6f91d5 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 3 Mar 2026 20:57:42 +0100 Subject: [PATCH 035/122] update docs --- docs/extra-library/actors/metrics.md | 548 +++------------------------ 1 file changed, 54 insertions(+), 494 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index efc4f8acc..67c4cb737 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -1,37 +1,15 @@ # Metrics -The metrics actor provides observability for Ergo applications by collecting and exposing runtime statistics in Prometheus format. Instead of manually instrumenting your code with counters and gauges scattered throughout, the metrics actor centralizes telemetry into a single process that exposes an HTTP endpoint for Prometheus to scrape. +The metrics actor collects runtime statistics from an Ergo node and exposes them as a Prometheus HTTP endpoint. It runs as a regular process -- spawn it, and it starts serving `/metrics` with node, network, process, and event telemetry. -This approach separates monitoring concerns from application logic. Your actors focus on business functionality while the metrics actor handles collection, aggregation, and exposure of operational data. Prometheus or compatible monitoring systems poll the `/metrics` endpoint periodically, building time-series data for alerting and visualization. +For application-specific metrics (request rates, business counters), you extend the actor with custom Prometheus collectors. ## Why Monitor Actors -Actor systems present unique monitoring challenges. Traditional thread-based applications have predictable resource usage patterns - you monitor thread pools, request queues, and database connections. Actor systems are more dynamic - processes spawn and terminate constantly, messages flow asynchronously through mailboxes, and work distribution depends on supervision trees and message routing. - -The metrics actor addresses this by tracking: - -**Process metrics** - How many processes exist, how many are running vs. idle vs. zombie. This reveals whether your node is under load or experiencing process leaks. - -**Mailbox metrics** - Queue depth and latency for every process on the node. Depth shows how many messages are waiting in each mailbox; latency shows how long the oldest message has been waiting. Together they answer whether actors are keeping up with their workload and which specific processes are falling behind. - -**Utilization and throughput metrics** - How much time each process spends executing callbacks relative to its lifetime, and how many messages flow through the node per second. These reveal compute-bound actors, idle capacity, and overall system throughput. - -**Memory metrics** - Heap allocation and actual memory used. Actor systems can accumulate small allocations across thousands of processes. Memory metrics help identify whether garbage collection keeps pace with allocation. - -**Network metrics** - For distributed Ergo clusters, tracking bytes and messages flowing between nodes reveals network bottlenecks, routing inefficiencies, or failing connections. Connection churn counters and per-acceptor handshake error rates detect network instability in static clusters where connection state should be stable between deploys. - -**Delivery error metrics** - Message delivery can fail for local reasons (target process unknown, terminated, or mailbox full) and remote reasons (connection failure). Separate counters for Send and Call errors, split by local and remote, help distinguish between overloaded processes and network problems. - -**Event metrics** - For pub/sub events, tracking which events have the most subscribers, which generate the most delivery load, and which are wasteful (publishing into the void or registered but unused). These reveal whether your event-driven architecture is efficient or accumulating overhead. See [Events](../../basics/events.md) for the pub/sub model and [Pub/Sub Internals](../../advanced/pub-sub-internals.md) for the shared subscription optimization that affects how delivery counters work. - -**Application metrics** - How many applications are loaded and running. Applications failing to start or terminating unexpectedly appear in these counts. - -These base metrics provide system-level visibility. For application-specific metrics (request rates, business transactions, custom counters), you extend the metrics actor with your own Prometheus collectors. +Actor systems are dynamic. Processes spawn and terminate constantly, messages flow through mailboxes asynchronously, and load depends on message routing and supervision trees. Traditional monitoring (thread pools, request queues) does not capture this. The metrics actor tracks process lifecycle, mailbox pressure, message throughput, event fanout, network traffic, and delivery errors -- giving visibility into what the actor runtime is actually doing. ## ActorBehavior Interface -The metrics actor extends `gen.ProcessBehavior` with a specialized interface: - ```go type ActorBehavior interface { gen.ProcessBehavior @@ -48,32 +26,16 @@ type ActorBehavior interface { } ``` -Only `Init()` is required - register your custom metrics and return options; all other callbacks have default implementations you can override as needed. - -You have two main patterns: - -**Periodic collection** - Implement `CollectMetrics()` to query state at intervals. Use when metrics reflect current state from other actors or external sources. - -**Event-driven updates** - Implement `HandleMessage()` or `HandleEvent()` to update metrics when events occur. Use when your application produces natural event streams or publishes events. - -## How It Works +Only `Init()` is required. All other callbacks have default implementations. -When you spawn the metrics actor: +Two patterns for custom metrics: -1. **HTTP endpoint starts** at the configured host and port. The `/metrics` endpoint immediately serves Prometheus-formatted data. +**Periodic collection** -- implement `CollectMetrics()` to query state at intervals. Use when metrics reflect current state from other actors or external sources. -2. **Base metrics collect automatically**. Node information (processes, memory, CPU), network statistics (connected nodes, message rates), per-process metrics (mailbox depth, utilization, latency, aggregates), and per-event metrics (utilization state, subscriber counts, delivery rates) update at the configured interval. - -3. **Custom metrics update** via `CollectMetrics()` callback or `HandleMessage()` processing, depending on your implementation. - -4. **Prometheus scrapes** the `/metrics` endpoint and receives current values for all registered collectors (base + custom). - -The actor handles HTTP serving and registry management. You focus on defining metrics and updating their values. +**Event-driven updates** -- implement `HandleMessage()` or `HandleEvent()` to update metrics as events occur. Use when your application produces natural event streams. ## Basic Usage -Spawn the metrics actor like any other process: - ```go package main @@ -87,7 +49,6 @@ func main() { node, _ := ergo.StartNode("mynode@localhost", gen.NodeOptions{}) defer node.Stop() - // Spawn metrics actor with defaults node.Spawn(metrics.Factory, gen.ProcessOptions{}, metrics.Options{}) // Metrics available at http://localhost:3000/metrics @@ -102,241 +63,93 @@ Default configuration: - **CollectInterval**: `10 seconds` - **TopN**: `50` -The HTTP endpoint starts automatically during initialization. The first metrics collection happens immediately, and subsequent collections run at the configured interval. - ## Configuration -Customize the HTTP endpoint and collection frequency: - ```go options := metrics.Options{ Host: "0.0.0.0", // Listen on all interfaces - Port: 9090, // Prometheus default port - Path: "/metrics", // HTTP path (default: "/metrics") - CollectInterval: 5 * time.Second, // Collect every 5 seconds - TopN: 50, // Top-N entries for each metric group (processes and events) + Port: 9090, // HTTP port + Path: "/metrics", // HTTP path + CollectInterval: 5 * time.Second, // Collection frequency + TopN: 50, // Top-N entries per metric group } node.Spawn(metrics.Factory, gen.ProcessOptions{}, options) ``` -**Host** determines which network interface the HTTP server binds to. Use `"localhost"` to restrict access to local connections only (development, testing). Use `"0.0.0.0"` to accept connections from any interface (production, containerized environments). - -**Port** should not conflict with other services. Prometheus conventionally uses `9090`, but many Ergo applications use that for other purposes. Choose a port that doesn't collide with your application's HTTP servers, Observer UI (default `9911`), or other metrics exporters. +**Host** determines which interface the HTTP server binds to. Use `"localhost"` for development, `"0.0.0.0"` for production/containers. -**Path** sets the HTTP path where the Prometheus handler is registered. Default is `"/metrics"`. Change it when the default path conflicts with your application's routing or when you need metrics at a non-standard location behind a reverse proxy. +**Port** should not conflict with other services. Prometheus conventionally uses `9090`, Observer UI defaults to `9911`. -**TopN** sets how many top entries are tracked for each metric group -- mailbox depth, utilization, latency for processes, and subscribers, published, local sent, remote sent for events (default: 50). Higher values provide more visibility but increase Prometheus cardinality. Set to 0 is not supported; the minimum effective value is 1. +**TopN** controls how many top entries are tracked for each metric group (mailbox depth, utilization, latency for processes; subscribers, published, deliveries for events). Higher values increase Prometheus cardinality. -**CollectInterval** controls how frequently the actor queries node statistics. Shorter intervals provide more granular time-series data but increase CPU usage for collection. Longer intervals reduce overhead but miss short-lived spikes. For most applications, 10-15 seconds balances responsiveness with resource usage. Prometheus typically scrapes every 15-60 seconds, so collecting more frequently than your scrape interval wastes resources. +**CollectInterval** controls how frequently the actor queries node statistics. Collecting more frequently than your Prometheus scrape interval wastes resources. -**Mux** accepts an external `*http.ServeMux`. When provided, the metrics actor registers its handler on this mux and skips starting its own HTTP server. This is useful when you want to serve metrics alongside other HTTP handlers on a single port -- for example, combining the metrics endpoint with the [Health](health.md) actor endpoints or your own application handlers. When `Mux` is set, `Host` and `Port` are ignored. +**Mux** accepts an external `*http.ServeMux`. The metrics actor registers its handler on this mux and skips starting its own HTTP server. Useful for serving metrics alongside other handlers on a single port: ```go mux := http.NewServeMux() -// Metrics actor registers /metrics on this mux metricsOpts := metrics.Options{ Mux: mux, CollectInterval: 5 * time.Second, } node.Spawn(metrics.Factory, gen.ProcessOptions{}, metricsOpts) -// Health actor registers /health/* on the same mux healthOpts := health.Options{Mux: mux} node.SpawnRegister("health", health.Factory, gen.ProcessOptions{}, healthOpts) - -// Serve the shared mux yourself ``` +When `Mux` is set, `Host` and `Port` are ignored. + ## Base Metrics -The metrics actor automatically exposes these Prometheus metrics without any configuration: +The actor automatically collects metrics without any configuration. All metrics carry a `node` label identifying the source node. ### Node Metrics -| Metric | Type | Description | -|--------|------|-------------| -| `ergo_node_uptime_seconds` | Gauge | Time since node started. Useful for detecting node restarts and calculating availability. | -| `ergo_processes_total` | Gauge | Total number of processes including running, idle, and zombie. High counts suggest process leaks or inefficient cleanup. | -| `ergo_processes_running` | Gauge | Processes actively handling messages. Low relative to total suggests most processes are idle (good) or blocked (bad - investigate what they're waiting for). | -| `ergo_processes_zombie` | Gauge | Processes terminated but not yet fully cleaned up. These should be transient. Persistent zombies indicate bugs in termination handling. | -| `ergo_processes_spawned_total` | Gauge | Cumulative number of successfully spawned processes since node start. Monotonically increasing counter useful for tracking spawn rate over time. | -| `ergo_processes_spawn_failed_total` | Gauge | Cumulative number of failed spawn attempts. Non-zero values indicate initialization errors or resource constraints preventing process creation. | -| `ergo_processes_terminated_total` | Gauge | Cumulative number of terminated processes. Compare to spawned count to understand process lifecycle patterns. | -| `ergo_memory_used_bytes` | Gauge | Total memory obtained from OS (uses `runtime.MemStats.Sys`). | -| `ergo_memory_alloc_bytes` | Gauge | Bytes of allocated heap objects (uses `runtime.MemStats.Alloc`). | -| `ergo_cpu_user_seconds` | Gauge | CPU time spent executing user code. Increases as the node does work. Rate of change indicates CPU utilization. | -| `ergo_cpu_system_seconds` | Gauge | CPU time spent in kernel (system calls). High system time relative to user time suggests I/O bottlenecks or excessive syscalls. | -| `ergo_cpu_cores` | Gauge | Number of CPU cores available to the process. Useful for normalizing CPU utilization metrics. | -| `ergo_applications_total` | Gauge | Number of applications loaded. Should match your expected count. Unexpected changes indicate applications starting or stopping. | -| `ergo_applications_running` | Gauge | Applications currently active. Compare to total to identify stopped or failed applications. | -| `ergo_registered_names_total` | Gauge | Processes registered with atom names. High counts suggest heavy use of named processes for routing. | -| `ergo_registered_aliases_total` | Gauge | Total number of registered aliases. Includes aliases created by processes via `CreateAlias()` and aliases identifying meta-processes. | -| `ergo_registered_events_total` | Gauge | Total number of registered events on this node. | -| `ergo_events_published_total` | Gauge | Cumulative number of events published by local producers. Use `rate()` to get publish throughput. | -| `ergo_events_received_total` | Gauge | Cumulative number of events received from remote nodes. Shows incoming event traffic load. | -| `ergo_events_local_sent_total` | Gauge | Cumulative number of event messages delivered to local subscribers. This reflects the actual fanout load -- a single publish with 100 subscribers produces 100 local deliveries. | -| `ergo_events_remote_sent_total` | Gauge | Cumulative number of event messages sent to remote nodes. Due to shared subscription optimization, one message is sent per remote node regardless of how many subscribers that node has. See [Pub/Sub Internals](../../advanced/pub-sub-internals.md). | -| `ergo_send_errors_local_total` | Gauge | Cumulative local Send delivery errors (target process unknown, terminated, or mailbox full). Non-zero rate indicates processes sending to stale PIDs or overloaded recipients. | -| `ergo_send_errors_remote_total` | Gauge | Cumulative remote Send delivery errors (connection failure to the target node). Non-zero rate indicates network connectivity problems. | -| `ergo_call_errors_local_total` | Gauge | Cumulative local Call delivery errors (same causes as local Send errors). | -| `ergo_call_errors_remote_total` | Gauge | Cumulative remote Call delivery errors (same causes as remote Send errors). | +Uptime, process counts (total, running, zombie), spawn/termination counters, memory (OS used, runtime allocated), CPU time (user, system), application counts, registered names/aliases/events, event publish/receive/delivery counters, and Send/Call delivery error counters (local and remote). + +Delivery errors are split by type: `ergo_send_errors_local_total` and `ergo_call_errors_local_total` count failures where the target process is unknown, terminated, or has a full mailbox. `ergo_send_errors_remote_total` and `ergo_call_errors_remote_total` count connection failures to remote nodes. ### Log Metrics -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_log_messages_total` | Gauge | `level` | Cumulative number of log messages by level. Labels: `trace`, `debug`, `info`, `warning`, `error`, `panic`. Counting happens once in the node's log dispatcher before fan-out to loggers, so the numbers are accurate regardless of how many loggers are registered. Use `rate()` to detect error spikes or `increase()` to compare levels over time. | +Log message count by level (`trace`, `debug`, `info`, `warning`, `error`, `panic`). Counted once before fan-out to loggers. ### Network Metrics -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_connections_established_total` | Gauge | - | Cumulative connections established. In a static cluster between deploys, `rate()` should be near zero. Sustained rate indicates connection churn or nodes restarting. | -| `ergo_connections_lost_total` | Gauge | - | Cumulative connections lost. Use with `ergo_connections_established_total` to detect network instability. | -| `ergo_acceptor_handshake_errors_total` | Gauge | `acceptor` | Cumulative handshake errors per acceptor interface. Non-zero rate indicates incoming connections with wrong protocol, authentication failures, or incompatible versions. | -| `ergo_connected_nodes_total` | Gauge | - | Number of remote nodes connected. For distributed systems, this should match your expected cluster size. | -| `ergo_remote_node_uptime_seconds` | Gauge | `remote_node` | Uptime of each connected remote node. Resets when the remote node restarts. | -| `ergo_remote_messages_in_total` | Gauge | `remote_node` | Messages received from each remote node. Rate indicates traffic volume. | -| `ergo_remote_messages_out_total` | Gauge | `remote_node` | Messages sent to each remote node. Asymmetric in/out rates may reveal routing issues. | -| `ergo_remote_bytes_in_total` | Gauge | `remote_node` | Bytes received from each remote node. Disproportionate bytes-to-messages ratio suggests large messages or inefficient serialization. | -| `ergo_remote_bytes_out_total` | Gauge | `remote_node` | Bytes sent to each remote node. Monitors network bandwidth usage per peer. | - -Network metrics use labels (`remote_node="..."`) to separate per-node data. This creates multiple time series - one per connected node. Prometheus queries can aggregate across labels or filter to specific nodes. +Connected node count, per-node uptime, message and byte rates (in/out per remote node), cumulative connections established/lost, and per-acceptor handshake error count. ### Mailbox Latency Metrics -When built with `-tags=latency`, the metrics actor automatically collects per-process mailbox latency data. This enables detection of stressed processes whose mailboxes are growing. - -```bash -go build -tags=latency ./... -``` - -Without the tag, latency measurement is disabled and no additional metrics are registered. There is zero overhead. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_mailbox_latency_distribution` | Gauge | `range` | Number of processes in each latency range. Snapshot per collect cycle -- values reflect the current state, not cumulative history. | -| `ergo_mailbox_latency_max_seconds` | Gauge | - | Maximum mailbox latency across all processes on this node. When this exceeds 1 second, at least one process is significantly behind. | -| `ergo_mailbox_latency_processes` | Gauge | - | Number of processes with non-empty mailbox (latency > 0). High count relative to total processes indicates widespread backpressure. | -| `ergo_mailbox_latency_top_seconds` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by mailbox latency. Directly identifies which processes are the bottlenecks. | - -The distribution metric uses gauge-based snapshots rather than a Prometheus histogram. Each collect cycle iterates over all processes, counts how many fall into each latency range, and sets the gauge values from scratch. This approach is a better fit for periodic state observation than cumulative histograms, which are designed for discrete events like HTTP requests. The ranges are: 1ms, 5ms, 10ms, 50ms, 100ms, 500ms, 1s, 5s, 10s, 30s, 60s, and 60s+. Each range represents an upper boundary -- for example, "5ms" counts processes with latency between 1ms and 5ms. - -The `TopN` option (default: 50) controls how many processes appear in the top-N metric. The same setting applies to all per-process top-N metrics (latency, depth, utilization). +Requires building with `-tags=latency`. Measures how long the oldest message has been waiting in each process's mailbox. Provides distribution across ranges (1ms to 60s+), max latency, and top-N processes by latency. ### Mailbox Depth Metrics -The metrics actor collects per-process mailbox queue depth -- the number of messages waiting in the mailbox at the moment of collection. While latency measures how long the oldest message has been waiting, depth measures how many messages are queued. The two metrics are complementary: a process may have high depth with low latency if it processes messages quickly but receives many at once, or low depth with high latency if a single message is taking a long time to process. - -No build tags required. Depth metrics are always active. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_mailbox_depth_distribution` | Gauge | `range` | Number of processes in each depth range. Snapshot per collect cycle. | -| `ergo_mailbox_depth_max` | Gauge | - | Maximum mailbox depth across all processes on this node. | -| `ergo_mailbox_depth_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by mailbox depth. | - -Distribution ranges: 1, 5, 10, 50, 100, 500, 1K, 5K, 10K, 10K+. Each range represents an upper boundary. Processes with empty mailboxes are not counted. - -### Process Utilization Metrics - -The metrics actor collects per-process utilization -- the ratio of callback running time to process uptime. A process that has been alive for 100 seconds and spent 30 of those seconds inside callbacks has a utilization of 0.30 (30%). This is a lifetime average computed from cumulative counters that the framework maintains for each process. It answers the question "which actors have been busiest over their entire lifetime?" - -Utilization is not the same as current CPU load. A process that was heavily loaded an hour ago but is idle now will still show high lifetime utilization. For current load, the dashboard provides `rate(ergo_process_running_time_seconds)` which shows how much callback time is happening right now per second. - -No build tags required. Utilization metrics are always active. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_process_utilization_distribution` | Gauge | `range` | Number of processes in each utilization range. Snapshot per collect cycle. | -| `ergo_process_utilization_max` | Gauge | - | Maximum process utilization on this node. | -| `ergo_process_utilization_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by utilization. | +Always active. Counts messages queued in each process's mailbox. Distribution across ranges (1 to 10K+), max depth, and top-N processes by depth. Complementary to latency: depth is "how many messages are waiting", latency is "how long the oldest has been waiting". -Distribution ranges: 1%, 5%, 10%, 25%, 50%, 75%, 90%, 90%+. Processes with zero running time or zero uptime are excluded. Utilization is capped at 1.0 (100%). +### Process Metrics -### Process Init Time Metrics +Always active. Includes: -The metrics actor tracks how long each process spent in its `ProcessInit` callback. This identifies actors with slow initialization -- heavy setup, blocking I/O, or synchronous calls during init. The default init timeout is 5 seconds (`DefaultRequestTimeout`), maximum 15 seconds for remote spawn. - -No build tags required. Init time metrics are always active. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_process_init_time_max_seconds` | Gauge | - | Maximum ProcessInit duration across all processes on this node. | -| `ergo_process_init_time_top_seconds` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by ProcessInit duration. | - -### Process Throughput Metrics - -The metrics actor tracks per-process message throughput (top-N by messages received and sent) and computes node-level aggregate counters by summing per-process values. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_process_messages_in_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by total messages received. Identifies which actors handle the most inbound traffic. | -| `ergo_process_messages_out_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by total messages sent. Identifies which actors generate the most outbound traffic. | -| `ergo_process_messages_in` | Gauge | - | Sum of messages received by all processes on this node. | -| `ergo_process_messages_out` | Gauge | - | Sum of messages sent by all processes on this node. | -| `ergo_process_running_time_seconds` | Gauge | - | Sum of callback running time across all processes on this node (seconds). | - -Aggregate values are cumulative -- apply `rate()` in Prometheus to get per-second rates. When a process terminates, its contribution is removed from the sum, which may cause the aggregate to decrease momentarily. This is expected and `rate()` handles it correctly in most cases. - -`rate(ergo_process_messages_in)` and `rate(ergo_process_messages_out)` give the node-level message throughput in messages per second. `rate(ergo_process_running_time_seconds)` gives the node-level actor CPU utilization in seconds of callback execution per second -- when this value approaches the number of available CPU cores, the node is compute-saturated. - -### Process Wakeups and Drains Metrics - -The metrics actor tracks process wakeups (transitions from Sleep to Running state) and drains (messages processed per wakeup). A wakeup occurs each time the framework starts a new goroutine to handle messages in a process's mailbox. The drain ratio (`MessagesIn / Wakeups`) reveals the nature of a process's load that utilization alone cannot distinguish. Two processes with 80% utilization may have completely different workloads: one with drain ~1 processes individual messages slowly (heavy per-message computation), while one with drain ~100 processes messages quickly but receives so many that it never sleeps (high throughput load). The optimization strategy is different: the first needs faster callbacks, the second needs load distribution. - -No build tags required. Wakeups and drains metrics are always active. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_process_wakeups_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by cumulative wakeup count. | -| `ergo_process_drains_top` | Gauge | `pid`, `name`, `application`, `behavior` | Top-N processes by drain ratio (MessagesIn / Wakeups). | -| `ergo_process_wakeups` | Gauge | - | Sum of wakeups across all processes on this node. | - -On the dashboard, the Throughput panels show wakeup rate as a third line alongside message in/out rates -- the visual gap between message rate and wakeup rate represents the drain effect. Drains per Node timeseries shows per-node drain ratio over time computed from aggregate metrics: `rate(messages_in) / rate(wakeups)`. +- **Utilization** -- ratio of callback running time to uptime. Distribution, max, and top-N. +- **Init time** -- ProcessInit duration. Max and top-N. +- **Throughput** -- messages in/out per process (top-N) and node-level aggregates. +- **Wakeups and drains** -- wakeup count and drain ratio (messages processed per wakeup). Drain ratio distinguishes between slow callbacks (drain ~1) and high-throughput batching (drain ~100) at the same utilization level. ### Event Metrics -The metrics actor collects per-event pub/sub metrics using `Node.EventRangeInfo()`, which iterates over all registered events and returns their current statistics. This provides visibility into the pub/sub layer: which events have the most subscribers, which generate the most delivery load, and which are wasteful. The subscriber count for each event includes both `LinkEvent` and `MonitorEvent` subscribers. - -No build tags required. Event metrics are always active. - -| Metric | Type | Labels | Description | -|--------|------|--------|-------------| -| `ergo_event_subscribers_max` | Gauge | - | Maximum subscriber count across all events on this node. | -| `ergo_event_utilization` | Gauge | `state` | Number of events in each utilization state. Snapshot per collect cycle. | -| `ergo_event_subscribers_top` | Gauge | `event`, `producer` | Top-N events by subscriber count. | -| `ergo_event_published_top` | Gauge | `event`, `producer` | Top-N events by messages published. | -| `ergo_event_local_sent_top` | Gauge | `event`, `producer` | Top-N events by messages delivered to local subscribers. | -| `ergo_event_remote_sent_top` | Gauge | `event`, `producer` | Top-N events by messages sent to remote nodes. | - -The utilization metric classifies every registered event into exactly one state: +Always active. Per-event subscriber count, publish/delivery counts, and utilization state (`active`, `on_demand`, `idle`, `no_subscribers`, `no_publishing`). See [Events](../../basics/events.md) for the pub/sub model and [Pub/Sub Internals](../../advanced/pub-sub-internals.md) for the shared subscription optimization that affects delivery counters. -- **`active`** -- has both published messages and subscribers. The event is doing its job -- producing and delivering messages. -- **`on_demand`** -- the event was registered with `Notify` enabled and is currently waiting (either no subscribers yet, or subscribers present but producer hasn't started). This is the expected state for on-demand producers that use `MessageEventStart`/`MessageEventStop` to control when they publish. See [Events](../../basics/events.md) for the `Notify` mechanism. -- **`idle`** -- registered without `Notify`, has zero subscribers and zero publishes. Likely a forgotten event consuming resources without purpose. -- **`no_subscribers`** -- has published messages but currently no subscribers, registered without `Notify`. The producer is doing work (serialization, message construction) for nothing. -- **`no_publishing`** -- has subscribers waiting but the producer has never published, registered without `Notify`. Could indicate a bug where the producer publishes to the wrong event name, or a producer that hasn't received its data source yet. - -The total across all states equals the total number of registered events on the node. A healthy system shows mostly `active` and `on_demand`. Growth in `idle` or `no_subscribers` over time indicates accumulating waste. - -The distinction between `published`, `local_sent`, and `remote_sent` in the top-N metrics reflects the pub/sub delivery model. A single publish fans out to all local subscribers (so `local_sent` can be much larger than `published`) and sends one message per remote subscriber node (due to the [shared subscription optimization](../../advanced/pub-sub-internals.md)). Comparing these values reveals the actual delivery cost of each event. - -### Per-Process Metrics Collection - -All per-process metrics (latency, depth, utilization, throughput, wakeups/drains, init time, aggregates) are collected in a single pass using `Node.ProcessRangeShortInfo()`. The iterator visits each process once, and each observation is dispatched to the latency, depth, utilization, and throughput collectors simultaneously. Event metrics are collected separately using `Node.EventRangeInfo()`, which iterates over all registered events. Both iterators use snapshot-then-iterate: the data is captured under a read lock, then the lock is released before the callback runs, so collection does not block producers or subscribers. Top-N selection uses a min-heap for O(N) efficiency. +For the complete list of metric names, types, labels, and descriptions, see the [metrics actor README](https://github.com/ergo-services/actor). ## Custom Metrics -There are three approaches to custom metrics depending on your use case: helper functions from any actor, embedding `metrics.Actor` for direct registry access, and shared mode for high-throughput scenarios. - -All custom metrics automatically receive a `node` const label set to the node name. Do not include `"node"` in your variable label names -- it will cause a "duplicate label names" registration error. +All custom metrics automatically receive a `node` const label. Do not include `"node"` in your variable label names. ### Helper Functions -Any actor on the same node can register and update custom metrics without importing `prometheus` or embedding the metrics actor. Registration is a synchronous Call (returns error on failure). Updates are asynchronous Send (fire-and-forget). +Any actor on the same node can register and update custom metrics without importing `prometheus` or embedding the metrics actor: ```go // Register metrics (sync Call, returns error) @@ -353,24 +166,17 @@ metrics.HistogramObserve(w, "metrics_actor", "request_seconds", 0.023, []string{ metrics.Unregister(w, "metrics_actor", "db_connections") ``` -The first argument is the calling process (`gen.Process`), the second is the target metrics actor (name, PID, or alias). When the registering process terminates, the metrics actor automatically unregisters all metrics it owned. - -This is the simplest approach. Use it when actors just need to report values without owning Prometheus collector objects. +When the registering process terminates, the metrics actor automatically unregisters all metrics it owned. ### Embedding metrics.Actor -For direct access to the Prometheus registry, periodic collection via `CollectMetrics`, or event-driven updates via `HandleMessage`, embed `metrics.Actor`. - -#### Periodic Collection - -Implement `CollectMetrics()` to poll state at regular intervals: +For direct access to the Prometheus registry or periodic collection via `CollectMetrics`: ```go type AppMetrics struct { metrics.Actor - activeUsers prometheus.Gauge - queueDepth prometheus.Gauge + activeUsers prometheus.Gauge } func (m *AppMetrics) Init(args ...any) (metrics.Options, error) { @@ -379,12 +185,7 @@ func (m *AppMetrics) Init(args ...any) (metrics.Options, error) { Help: "Current number of active users", }) - m.queueDepth = prometheus.NewGauge(prometheus.GaugeOpts{ - Name: "myapp_queue_depth", - Help: "Current queue depth", - }) - - m.Registry().MustRegister(m.activeUsers, m.queueDepth) + m.Registry().MustRegister(m.activeUsers) return metrics.Options{ Port: 9090, @@ -393,138 +194,52 @@ func (m *AppMetrics) Init(args ...any) (metrics.Options, error) { } func (m *AppMetrics) CollectMetrics() error { - // Called every CollectInterval - // Query other processes for current state - count, err := m.Call(userService, getActiveUsersMessage{}) if err != nil { m.Log().Warning("failed to get user count: %s", err) - return nil // Non-fatal, continue + return nil } m.activeUsers.Set(float64(count.(int))) - - depth, _ := m.Call(queueService, getDepthMessage{}) - m.queueDepth.Set(float64(depth.(int))) - return nil } ``` -Use this when metrics reflect state you need to query - current values from other actors, computed aggregates, external API calls. - -#### Event-Driven Updates - -Update metrics immediately when events occur: +For event-driven updates, implement `HandleMessage()` instead of `CollectMetrics()`: ```go -type AppMetrics struct { - metrics.Actor - - requestsTotal prometheus.Counter - errorsTotal prometheus.Counter - requestLatency prometheus.Histogram -} - -func (m *AppMetrics) Init(args ...any) (metrics.Options, error) { - m.requestsTotal = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "myapp_requests_total", - Help: "Total requests processed", - }) - - m.errorsTotal = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "myapp_errors_total", - Help: "Total errors occurred", - }) - - m.requestLatency = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "myapp_request_duration_seconds", - Help: "Request latency distribution", - Buckets: prometheus.DefBuckets, - }) - - m.Registry().MustRegister(m.requestsTotal, m.errorsTotal, m.requestLatency) - - return metrics.Options{Port: 9090}, nil -} - func (m *AppMetrics) HandleMessage(from gen.PID, message any) error { switch msg := message.(type) { case requestCompletedMessage: m.requestsTotal.Inc() m.requestLatency.Observe(msg.duration.Seconds()) - case errorOccurredMessage: - m.errorsTotal.Inc() - } - return nil -} -``` - -Application actors send events to the metrics actor: - -```go -// In your request handler actor -func (h *RequestHandler) HandleMessage(from gen.PID, message any) error { - switch msg := message.(type) { - case ProcessRequest: - start := time.Now() - // ... process request ... - elapsed := time.Since(start) - - // Send metrics event - h.Send(metricsPID, requestCompletedMessage{duration: elapsed}) } return nil } ``` -Use this when your application naturally produces events. Metrics update in real-time without polling. - ### Shared Mode -A single metrics actor handles all custom metric operations sequentially -- registration, updates, and unregistration pass through one mailbox. Under high throughput this becomes a bottleneck: hundreds of actors sending gauge updates or histogram observations compete for the same process, and the mailbox grows faster than callbacks can drain it. - -Shared mode solves this by separating the Prometheus registry from the actor. You create a `metrics.Shared` object that holds the registry and a thread-safe map of registered metrics. Multiple metrics actor instances share this object -- each one can serve updates independently because Prometheus collectors are safe for concurrent use. Registration still serializes through a single actor (to avoid duplicate metric names), but updates go to any worker in a pool. - -Create the shared object and pass it to all metrics actors that should share the same registry: +A single metrics actor processes messages sequentially. Under high throughput, its mailbox becomes a bottleneck. Shared mode lets multiple metrics actor instances share the same Prometheus registry: ```go shared := metrics.NewShared() -// Primary actor: owns the HTTP endpoint and base Ergo metrics +// Primary actor: owns HTTP endpoint and base metrics primaryOpts := metrics.Options{ Port: 9090, Shared: shared, } -// Worker actors: handle custom metric updates only (no HTTP, no base metrics) +// Worker actors: handle custom metric updates only workerOpts := metrics.Options{ Shared: shared, } ``` -The primary actor starts the HTTP server and collects base Ergo metrics as usual. Worker actors skip HTTP and base collection -- they only process custom metric messages (register, update, unregister). All actors write to the same Prometheus registry through the shared object. - -This pattern works well with `act.Pool`: put worker actors behind a pool, and the pool distributes incoming metric updates across workers automatically. The `application/radar` package uses this approach internally. - -## Metric Types - -Prometheus defines four metric types, each suited for different use cases: - -**Counter** - Monotonically increasing value. Use for events that accumulate (requests processed, errors occurred, bytes sent). Counters never decrease except on process restart. Prometheus queries typically use `rate()` to calculate per-second rates or `increase()` for total change over a time window. - -**Gauge** - Value that can go up or down. Use for current state (active connections, queue depth, memory usage, CPU utilization). Gauges represent snapshots. Prometheus queries can graph them directly or use functions like `avg_over_time()` to smooth spikes. - -**Histogram** - Observations bucketed into configurable ranges. Use for latency or size distributions. Histograms let you calculate percentiles (p50, p95, p99) in Prometheus queries. They're more resource-intensive than gauges because they maintain multiple buckets per metric. - -**Summary** - Similar to histogram but calculates quantiles client-side. Use when you need precise quantiles but can't predict bucket boundaries. Summaries are more expensive than histograms because they track exact quantiles, not approximations. - -For most use cases, counters and gauges suffice. Use histograms when you need latency percentiles. Avoid summaries unless you have specific reasons - histograms are more flexible for Prometheus queries. - +The primary actor starts the HTTP server and collects base metrics. Workers only process custom metric messages. All actors write to the same registry through the shared object. Works well with `act.Pool` for automatic load distribution. ## Integration with Prometheus -Configure Prometheus to scrape the metrics endpoint: - ```yaml scrape_configs: - job_name: 'ergo-nodes' @@ -532,182 +247,27 @@ scrape_configs: - targets: - 'localhost:3000' - 'node1.example.com:3000' - - 'node2.example.com:3000' scrape_interval: 15s ``` -Prometheus fetches `/metrics` every 15 seconds, parses the text format, and stores time-series data. You can then query, alert, and visualize metrics using Prometheus queries or Grafana dashboards. - -For dynamic discovery in Kubernetes or cloud environments, use Prometheus service discovery instead of static targets. The metrics actor itself doesn't need to know about Prometheus - it just exposes an HTTP endpoint. +For dynamic discovery in Kubernetes, use Prometheus service discovery instead of static targets. ## Grafana Dashboard -The metrics package includes a pre-built Grafana dashboard (`ergo-cluster.json`) designed for monitoring Ergo clusters. The dashboard provides a comprehensive view of cluster health with automatic refresh every 10 seconds. - -### Importing the Dashboard - -1. Open Grafana and navigate to Dashboards -2. Click "Import" -3. Upload the `ergo-cluster.json` file from the metrics package or paste its contents -4. Select your Prometheus data source - -The dashboard includes a `$node` variable dropdown that filters all panels by selected nodes. By default, all nodes are displayed. - -### Understanding the Panels - -The dashboard organizes metrics into logical groups arranged from high-level overview at the top to detailed breakdowns below. Rows marked "collapsed" are hidden by default -- click the row header to expand them. - -**Summary Row** (expanded) - Six stat panels showing aggregated values: total processes, running processes, zombie count (red when non-zero), memory used, memory allocated, and node count. These provide immediate cluster health at a glance. The gap between total and running is normal -- most processes spend their time in Sleep state (idle, waiting for messages). Running counts only processes currently executing callbacks or waiting for a Call response. Non-zero zombies require investigation. - -**Mailbox Latency** (expanded, requires `-tags=latency`) - Six panels for latency analysis described in detail in the next section. When the `latency` tag is not used, these panels show "No data". - -**Mailbox Depth** (expanded) - Three panels showing mailbox queue depth. Max Depth per Node tracks the largest mailbox on each node over time. Depth Distribution is a stacked area chart with a flame color gradient (green for 1-10 messages, yellow for 50-100, orange for 500-1K, red for 5K-10K+) showing how many processes fall into each depth range. Top Processes by Depth is a table listing the processes with the deepest queues across the cluster. Depth is complementary to latency: depth tells you "how many messages are queued," while latency tells you "how long the oldest one has been waiting." - -**Events** (collapsed) - Ten panels for pub/sub event observability, organized from general to specific. Event Publish/Delivery Rate shows cluster-wide throughput with four lines: Published (local producer publish rate), Received (events arriving from remote nodes), Local Delivered (actual fanout to local subscribers), and Remote Sent (one message per remote node due to [shared subscriptions](../../advanced/pub-sub-internals.md)). Event Utilization is a stacked timeseries showing the state of all registered events: active (publishing with subscribers), on demand (using Notify, waiting), idle, no subscribers, no publishing. The total height equals total registered events; a healthy system is mostly green (active) and blue (on demand). Event Publish Rate per Node and Event Delivery Rate per Node show per-node publish and delivery rates. Registered Events per Node and Max Subscribers per Node provide per-node counts. Four tables at the bottom show Top Events by Subscribers, Published, Local Deliveries, and Remote Sent -- identifying which specific events create the most load. See [Events](../../basics/events.md) for the pub/sub model. - -**Process Activity** (collapsed) - Twelve panels organized by topic: message throughput, delivery errors, drains, then process utilization. Message Throughput (Cluster Total) and Message Throughput per Node show inbound, outbound, and wakeup rates -- the gap between message rate and wakeup rate reveals drain effect (processes batching under load). Top Processes by Messages In/Out tables identify which actors handle the most traffic. Delivery Errors (Cluster Total) shows cluster-wide rate of Send and Call failures split by local (process unknown, terminated, mailbox full) and remote (connection failure); Delivery Errors per Node breaks the same data down per node to identify which nodes have the most failures. Drains per Node timeseries shows per-node drain ratio over time (`rate(messages_in) / rate(wakeups)`), and Top Processes by Drains table identifies specific actors with the highest drain -- these are the processes that handle the most messages per wakeup cycle. Drain ratio complements utilization: two processes at 80% utilization may have drain ~1 (slow callbacks) or drain ~100 (fast callbacks, high volume) -- different problems needing different solutions. Utilization Distribution, Max Utilization per Node, Actor Running Time per Node, and Top Processes by Utilization cover compute load analysis. - -**Processes** (collapsed) - Six panels showing per-node process counts (total and running), lifecycle rates (spawn rate with failures in red, termination rate), and initialization performance (init time bar gauge per node, top processes by init time). Steady growth in total without plateau suggests process leaks. Spawn failures indicate resource exhaustion. When termination rate exceeds spawn rate, the node is draining. High init times indicate heavy initialization logic or blocking operations in ProcessInit. - -**Resources** (collapsed) - Four panels covering CPU and memory. CPU User Time and CPU System Time are normalized by core count and displayed as percentages. High user CPU means compute-bound workload; high system CPU relative to user suggests excessive I/O or syscalls. Memory (OS:used) and Memory (Runtime:alloc) show memory usage over time. Monotonic growth signals memory leaks. Sawtooth pattern in runtime allocation is normal (GC cycles). Rising baseline between GC cycles indicates uncollected objects. - -**Logging** (collapsed) - Log Messages Rate shows the rate of log messages per second broken down by level as a stacked area chart. Colors follow severity: trace and debug are gray, info is green, warning is yellow, error is red, panic is dark red. A healthy system shows mostly green (info). Spikes in warning or error indicate issues worth investigating. The legend table shows current, mean, and max rates per level. Counting happens once in the node's log dispatcher before fan-out to loggers, so the numbers are accurate regardless of how many loggers are registered. - -**Network** (collapsed) - Eight panels covering cluster totals, per-node breakdowns, node-pair detail for both message rates and byte rates, and connection health. Sudden drops may indicate partitions. Disproportionate bytes-to-messages ratio reveals large message sizes. The detail panels show traffic between specific node pairs, useful for tracing inter-node communication paths and identifying saturated links. Connected Nodes is a bar gauge showing connected remote nodes per node with color thresholds: red (0, isolated), orange (1, degraded), yellow (2, partial), green (3+, healthy). Connection Events shows per-node rates of connection established (green), lost (red), and handshake errors (orange) on a single chart -- in a stable cluster all three are zero. +The metrics package includes a pre-built Grafana dashboard (`ergo-cluster.json`) for monitoring Ergo clusters. -### Working with the Dashboard +Import it in Grafana: Dashboards > Import > upload `ergo-cluster.json` > select your Prometheus data source. The `$node` dropdown at the top filters all panels by selected nodes. -The dashboard is designed around a top-down investigation pattern. Start with the Summary row for cluster health, then drill into the relevant section based on the symptom you observe. +The dashboard is organized top-down: Summary row at the top for cluster health at a glance, then Mailbox Latency and Depth for backpressure analysis, then collapsed rows for Events, Process Activity, Processes, Resources, Logging, and Network. Each row focuses on a specific aspect of cluster behavior and can be expanded when investigating issues. -#### Routine check - -Open the dashboard and scan the Summary row: - -- **Zombie count should be zero.** Non-zero means processes have terminated abnormally and were not cleaned up. -- **Node count should match your expectation.** A drop means a node left the cluster. -- **Memory used should be within expected bounds.** A sharp increase suggests a leak or load spike. - -Then check the expanded rows below the Summary: - -- **Mailbox Latency** (if using `-tags=latency`) -- Max Latency under 100ms and Stressed Processes mostly empty or light-blue means healthy. If not using latency, check Mailbox Depth instead -- zero or low depth across all nodes is healthy. -- **Mailbox Depth** -- Max Depth per Node at zero or near zero is normal. - -For a deeper check, expand the collapsed rows: - -- **Events** -- Event Utilization should be mostly green (active) and blue (on demand). Growth in grey (idle) or orange (no subscribers) over time indicates accumulating waste. -- **Process Activity** -- Message Throughput should be stable. A sudden drop compared to the previous period may indicate stalled processes. - -#### Investigating backpressure - -Backpressure means processes are receiving messages faster than they can handle them. The Mailbox Latency and Mailbox Depth rows are the primary tools. - -**With `-tags=latency` enabled:** - -Max Latency shows the worst case across the cluster. Stressed Processes shows how many processes are affected. Read them together: - -- Max Latency spikes above 1 second -- at least one process is severely behind. Use the Top Stressed Processes table to identify it. -- Orange area growing in Stressed Processes -- multiple processes are falling behind. Check Latency Distribution to assess severity (isolated red sliver = one stuck process, chart shifting to orange = widespread degradation). -- Max Latency persistently elevated (minutes, not seconds) -- a stuck process, not a burst. Find it in the Top Stressed Processes table. - -Use Max Latency per Node and Stressed Processes per Node to narrow down: one node standing out = localized problem; all nodes affected = systemic issue (shared dependency, deployment, cluster-wide traffic pattern). - -**Without latency tag:** - -Max Depth per Node is the closest alternative. Rising depth means a process accumulates messages faster than it handles them. Depth Distribution shows severity. Top Processes by Depth identifies the specific actors. Depth is complementary to latency: depth tells you "how many messages are queued," latency tells you "how long the oldest has been waiting." - -#### Investigating throughput anomalies - -Expand the Process Activity row. The top two rows cover message throughput. - -- **Cluster Throughput drops suddenly** -- processes may be stalled or an upstream source stopped sending. Check if specific nodes dropped (Throughput per Node) or the entire cluster. -- **Cluster Throughput spikes** -- correlate with Mailbox Depth and Latency. A spike followed by growing depth means the system cannot absorb the burst. -- **In/Out imbalance** -- in a fully monitored cluster (metrics actor on every node), In and Out should be approximately balanced. A small imbalance is normal due to framework-internal messages (exit signals, down notifications) that increment In without a corresponding Out. Persistent significant imbalance indicates nodes without metrics collection: Out > In means messages are sent to unmonitored nodes, In > Out means unmonitored nodes are sending messages into the cluster. -- **One node has disproportionate throughput** -- Throughput per Node identifies hotspots. Cross-reference with Top Processes by Messages In/Out to find the specific actors. -- **Wakeup rate diverges from message rate** -- on Throughput panels, the gap between In and Wakeups lines shows drain effect. Growing gap means processes batch more messages per wakeup (increasing load). Drains per Node timeseries shows which node, Top Processes by Drains shows which process. - -#### Investigating process lifecycle issues - -Expand the Processes row. - -- **Steady growth in total process count** without plateau -- process leak. Processes are spawned but never terminated. Check which application spawns them using the process tables. -- **Spawn failures** (red in Process Spawn Rate) -- resource exhaustion or configuration errors preventing process creation. -- **Spawn rate spikes** -- may signal a supervisor restart loop. Correlate with termination rate -- if both spike together, a process keeps crashing and restarting. -- **Termination rate exceeds spawn rate** -- the node is draining. Check why processes are terminating (errors, shutdown, kills). -- **High init time** -- Init Time per Node bar gauge shows the slowest ProcessInit on each node with color-coded severity. Default timeout is 5 seconds. Top Processes by Init Time table identifies which actor types take the longest. High init times indicate heavy setup, blocking I/O, or synchronous calls during initialization. If init times approach the timeout, processes risk being killed before they finish starting. - -#### Investigating event issues - -Expand the Events row. - -- **Event Utilization shifting from green/blue to grey/orange** -- accumulating waste. Grey (idle) events are registered but unused. Orange (no subscribers) events are publishing into the void. Investigate which events are affected using the top-N tables. -- **Publish/Delivery Rate gap growing** -- Local Delivered >> Published indicates high fanout. If this correlates with latency increases on subscriber nodes, event fanout is causing backpressure. -- **One node has high Event Delivery Rate** -- that node handles the most event fanout. Cross-reference with Mailbox Depth and Latency for the same node. -- **Registered Events growing without plateau** -- event registration leak. Events are registered but never unregistered. Check Event Utilization for growing idle count. -- **Max Subscribers spike** -- one event suddenly gained many subscribers, amplifying the cost of each publish. - -#### Investigating resource saturation - -Expand the Resources row. - -- **CPU User Time approaching 100%** -- compute-bound. Correlate with Utilization Distribution in Process Activity to see which processes are consuming CPU. Actor Running Time per Node approaching CPU core count confirms saturation. -- **High System CPU relative to User CPU** -- excessive syscalls, context switching, or I/O pressure rather than application workload. -- **Memory monotonically growing** -- memory leak. Compare OS:used across nodes to spot outliers. Check if Mailbox Depth is also growing -- accumulating messages consume memory. -- **Runtime:alloc baseline rising between GC cycles** -- objects not being collected. The sawtooth pattern should return to a stable baseline. - -#### Investigating network issues - -Expand the Network row. - -- **Cluster total message rate drops suddenly** -- possible network partition or node failure. Check Node count in Summary and per-node breakdown. -- **One node-pair has disproportionate traffic** -- Network Detail panels show traffic between specific pairs. Identifies saturated links or unexpected communication patterns. -- **Bytes-to-messages ratio changing** -- average message size is growing. May indicate serialization issues or bulk data transfers. - -#### Cross-panel correlation - -Combining signals from different sections identifies root causes: - -- **High latency + high depth** -- process is both slow and receiving more than it can handle. Mailbox growing. Clearest sign of overload. -- **High latency + low depth** -- single message processed slowly (long callback) or process blocked on external resource. Mailbox not growing. -- **High depth + low latency** -- process receives bursts but handles them quickly. Usually transient. -- **High latency + high CPU** -- compute-bound. Actors doing heavy work in callbacks. Distribute work or offload computation. -- **High latency + low CPU** -- processes blocked on something other than computation. External I/O, synchronous calls to other actors, or contention. -- **High latency + growing memory** -- mailboxes accumulating messages. If this continues, the node runs out of memory. -- **High latency + network traffic spike** -- burst of remote messages overwhelming receivers. Check Network Detail panels. -- **High event delivery rate + high latency on same node** -- event fanout causing backpressure. Top Events by Local Deliveries identifies which event, Mailbox Depth/Latency shows the impact on subscribers. -- **High init time + spawn rate spikes** -- supervisor restart loop with slow init. Each restart takes seconds, creating cascading delays. -- **Throughput drop + stable process count** -- processes alive but not doing work. Blocked on external calls or upstream failure (no messages arriving). -- **Running time per node approaching CPU cores** -- node is compute-saturated. All CPU time spent in actor callbacks. Reduce workload or add capacity. -- **Event no_subscribers growing + stable throughput** -- producers publishing into the void. Not using [Notify](../../basics/events.md) mechanism to detect absent subscribers. -- **High drain + stable depth** -- process running at maximum capacity but keeping up. No action needed unless depth starts growing. -- **High drain + growing depth** -- process cannot keep up despite continuous processing. Needs load distribution or faster message handling. -- **High utilization + low drain** -- slow per-message processing. Each callback takes long. Optimize the callback logic. -- **High utilization + high drain** -- fast processing but overwhelming volume. Distribute load across more processes. +For detailed panel descriptions, see the [metrics actor README](https://github.com/ergo-services/actor). ## Observer Integration -The metrics actor includes built-in Observer support via `HandleInspect()`. When you inspect it in Observer UI (http://localhost:9911), you see: - -- Total number of registered metrics -- HTTP endpoint URL for Prometheus scraping -- Collection interval -- Current values for all metrics (base + custom) - -This works automatically for custom metrics -- register them in `Init()` and they appear in Observer alongside base metrics. - -If you embed `metrics.Actor` and override `HandleInspect()`, the base inspection data (endpoint, interval, metric values) is always included. Your returned keys are merged on top, so you can add custom fields or override base values: - -```go -func (m *AppMetrics) HandleInspect(from gen.PID, item ...string) map[string]string { - result := make(map[string]string) - // Add custom fields -- these merge with base data - result["status"] = "healthy" - result["custom_info"] = "some value" - return result -} -``` +The metrics actor integrates with Observer via `HandleInspect()`. Inspecting the process shows total metric count, HTTP endpoint, collection interval, and current values for all metrics. -For detailed configuration options, see the `metrics.Options` struct and `ActorBehavior` interface in the package. For examples of custom metrics, see the [metrics actor repository](https://github.com/ergo-services/actor). +When embedding `metrics.Actor` and overriding `HandleInspect()`, your keys are merged on top of base inspection data. ## Radar Application -If your node needs both Prometheus metrics and Kubernetes health probes, consider the [Radar](../applications/radar.md) application. It runs the metrics actor and health actor together on a single HTTP port and provides helper functions so your actors don't need to import either package directly. +If your node needs both Prometheus metrics and Kubernetes health probes, consider the [Radar](../applications/radar.md) application. It runs the metrics actor and [Health](health.md) actor together on a single HTTP port. From 73f9929f3d563af2fa37fbc39db893470c16c9d6 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 4 Mar 2026 13:14:33 +0100 Subject: [PATCH 036/122] update docs --- docs/networking/network-stack.md | 4 +- docs/networking/network-transparency.md | 71 +++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/docs/networking/network-stack.md b/docs/networking/network-stack.md index cd9558956..6a456de45 100644 --- a/docs/networking/network-stack.md +++ b/docs/networking/network-stack.md @@ -103,9 +103,7 @@ After handshake, the accepting node tells the dialing node to create a connectio The dialing node opens additional TCP connections using a shortened join handshake (skips full authentication since the first connection already authenticated). These connections join the pool, forming a single logical connection with multiple physical TCP links. -Multiple connections enable parallel message delivery. Each message goes to a connection based on the sender's identity (derived from sender PID). Messages from the same sender always use the same connection, preserving order. Messages from different senders use different connections, enabling parallelism. - -The receiving side creates 4 receive queues per TCP connection. A 3-connection pool has 12 receive queues processing messages concurrently. This parallel processing improves throughput while preserving per-sender message ordering. +Multiple connections enable parallel message delivery. Each message goes to a connection based on the sender's identity, and the receiving side creates multiple receive queues per TCP connection for concurrent processing. This two-level mechanism -- sender-side link selection and receiver-side queue routing -- preserves per-sender message ordering while enabling parallelism across different senders. For details on how ordering works, including the `KeepNetworkOrder` flag and when to disable it, see [Message Ordering](network-transparency.md#message-ordering). ## Message Encoding and Transmission diff --git a/docs/networking/network-transparency.md b/docs/networking/network-transparency.md index 0e2318310..173360a6e 100644 --- a/docs/networking/network-transparency.md +++ b/docs/networking/network-transparency.md @@ -430,6 +430,71 @@ The cost is latency. Normal `Send` returns immediately - it queues the message a For detailed exploration of Important Delivery patterns, reliability guarantees, and protocols like RR-2PC and FR-2PC, see [Important Delivery](../advanced/important-delivery.md). +## Message Ordering + +Messages sent from process A to process B arrive in sending order. This is a per-sender FIFO guarantee -- it applies to each sender independently, not globally across all senders. The guarantee is enabled by default for every process. + +### KeepNetworkOrder Flag + +Message ordering is controlled by a per-process flag called `KeepNetworkOrder`, which defaults to `true`. You can change it using `SetKeepNetworkOrder(bool)` during `Init` or at any point while the process is running. The flag applies to all outgoing messages from that process: `Send`, `Call`, `SendResponse`, and `SendEvent`. There is no per-message override -- ordering is all-or-nothing for a given sender. + +### How It Works -- Sender Side + +With ordering enabled, all messages from a process go through the same TCP link in the connection pool. The link is selected deterministically: `sender.ID % 255 % pool_size`. Since TCP guarantees FIFO delivery within a single connection, messages arrive at the remote node in exactly the order they were sent. + +With ordering disabled, messages are distributed round-robin across all pool links. This spreads the load for maximum throughput, but the arrival order across different TCP connections is no longer deterministic. + +### How It Works -- Receiver Side + +Each message carries an **order byte** in the protocol header (byte 6 of the ENP frame). When ordering is enabled, the order byte is derived from the recipient's identity: +- For `gen.PID` recipients: `to.ID % 255` +- For `gen.Alias` recipients: `to.ID[1] % 255` + +The receiving node routes messages to receive queues based on this byte: `order_byte % queue_count`. Messages destined for the same recipient land in the same queue and are decoded sequentially, preserving order. + +When ordering is disabled, the order byte is zero. Messages distribute round-robin across receive queues, enabling parallel decoding at the cost of non-deterministic arrival order. + +### Two-Level Guarantee + +The ordering mechanism works at two levels: + +1. **Sender side** -- pins messages to one TCP link, preserving send order in the TCP stream +2. **Receiver side** -- pins messages to one decode queue, preserving decode order + +Together they ensure end-to-end FIFO from sender to recipient. The sender side prevents reordering during transmission; the receiver side prevents reordering during decoding and dispatch. + +### Special Cases + +Some system messages have fixed ordering semantics regardless of the `KeepNetworkOrder` flag: + +| Operation | Ordering | Notes | +|-----------------|---------------|---------------------------------------------| +| `SendExit` | Always ordered| No `KeepNetworkOrder` check -- always uses sender-derived order byte | +| `SendTerminate` | Always unordered | Order byte is always 0 | +| Link/Monitor | Always ordered| System operations that must arrive in sequence | + +These are internal system messages where ordering behavior is fixed by the protocol, not configurable by the process. + +### When to Disable Ordering + +Processes that don't need ordering benefit from disabling it. When `KeepNetworkOrder` is `false`, messages spread across all TCP links in the pool and all receive queues on the remote side. This increases parallelism on both ends -- more connections are utilized for sending, and more goroutines participate in decoding. + +Good candidates for disabling ordering: +- **Stateless workers** that process each request independently +- **Fan-out producers** that distribute work to many recipients +- **High-throughput event emitters** where each event is self-contained + +The tradeoff is straightforward: message arrival order becomes non-deterministic. If your process logic doesn't depend on message order, disabling ordering gives you better throughput. + +```go +func (w *Worker) Init(args ...any) error { + // This worker processes requests independently, + // ordering doesn't matter + w.SetKeepNetworkOrder(false) + return nil +} +``` + ## Protocol Frame Structure EDF-encoded messages are wrapped in ENP (Ergo Network Protocol) frames for transmission over TCP. @@ -448,9 +513,7 @@ For PID messages, the frame contains: - Recipient PID (8 bytes) - EDF-encoded message payload -The **order byte** (byte 6) preserves message ordering per sender. It's calculated as `senderPID.ID % 255`, ensuring messages from the same sender have the same order value. This guarantees sequential processing on the receiving side even if messages arrive on different TCP connections in the pool. Messages from different senders have different order values, enabling parallel processing. - -When the receiving node reads a frame from TCP, it extracts the order byte and routes the frame to the appropriate receive queue. The connection creates **4 receive queues per TCP connection** in the pool. So a 3-connection pool has 12 receive queues total. Frames are distributed to queues based on `order_byte % queue_count`. Each queue is processed by a dedicated goroutine that decodes frames and delivers messages to recipients. This parallel processing improves throughput while preserving per-sender ordering. +The **order byte** (byte 6) controls message ordering and receive queue routing. For details on how the order byte is calculated and how it interacts with the connection pool and receive queues, see [Message Ordering](#message-ordering) above. ## Limits of Transparency @@ -464,7 +527,7 @@ Network transparency is powerful but not magical. The network has physical prope **Partial failures** - In a distributed system, some nodes can fail while others continue working. A local system either works entirely or crashes entirely. A distributed system can be partially operational - some nodes reachable, others not. This partial failure is the hardest aspect of distributed systems. The framework can't hide it entirely. -**Ordering** - Message ordering is preserved per-sender within a connection. Messages from process A to process B arrive in the order sent. But messages from different senders can interleave arbitrarily. And if a connection drops and reconnects, messages sent during disconnection are lost or delayed. Don't assume global ordering across the cluster. +**Ordering** - Message ordering is preserved per-sender, not globally. Messages from process A to process B arrive in sending order, but messages from different senders can interleave arbitrarily. If a connection drops and reconnects, messages sent during disconnection are lost or delayed. Don't assume global ordering across the cluster. See [Message Ordering](#message-ordering) for how the ordering mechanism works and when to disable it. Network transparency makes distributed programming feel local. But distributed programming has fundamental differences from local programming. The transparency is a tool that simplifies common cases - it doesn't eliminate the need to think about distributed system challenges. From c2bd989656db16feff3230170b431f1e005e7791 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 5 Mar 2026 17:33:14 +0100 Subject: [PATCH 037/122] fix connection pool: handle flusher errors --- CHANGELOG.md | 1 + README.md | 2 ++ lib/flusher.go | 16 ++++++++++++++-- net/proto/connection.go | 14 ++++++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86366108d..b8dd41dc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed **message counters for meta processes** - meta process traffic now propagates to parent process counters, making `ProcessRangeShortInfo` aggregates balanced * Fixed **self-send message counter** - `messagesOut` now incremented for self-sends * Fixed **simultaneous connect dead loop** - two nodes dialing each other at the same time no longer cause infinite retry loops. Deterministic connection IDs and Erlang-style collision detection (`EnableSimultaneousConnect` flag) ensure exactly one connection per pair. Fixed related connection leaks +* Fixed **silent data loss on connection pool write failure** - a transient write error could permanently break a pool item's write path without detection, causing all subsequent messages to be silently dropped while the connection appeared healthy #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index 412f95aef..5ca40681d 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,8 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Fixed **simultaneous connect dead loop** - two nodes dialing each other at the same time no longer cause infinite retry loops. Deterministic connection IDs and Erlang-style collision detection (`EnableSimultaneousConnect` flag) ensure exactly one connection per pair. Fixed related connection leaks +* Fixed **silent data loss on connection pool write failure** - a transient write error could permanently break a pool item's write path without detection, causing all subsequent messages to be silently dropped while the connection appeared healthy + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at diff --git a/lib/flusher.go b/lib/flusher.go index 1dd410ac5..6a48339a2 100644 --- a/lib/flusher.go +++ b/lib/flusher.go @@ -24,6 +24,7 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time // nothing to write. send keepalive. f.writer.Write(keepalive) if err := f.writer.Flush(); err != nil { + f.err = err return } @@ -31,7 +32,10 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time return } - f.writer.Flush() + if err := f.writer.Flush(); err != nil { + f.err = err + return + } f.pending = false f.timer.Reset(latency) }) @@ -53,7 +57,10 @@ func NewFlusher(w io.Writer) io.Writer { return } - f.writer.Flush() + if err := f.writer.Flush(); err != nil { + f.err = err + return + } f.pending = false f.timer.Reset(latency) }) @@ -65,12 +72,17 @@ type flusher struct { timer *time.Timer writer *bufio.Writer pending bool + err error } func (f *flusher) Write(b []byte) (n int, err error) { f.Lock() defer f.Unlock() + if f.err != nil { + return 0, f.err + } + l := len(b) // write data to the buffer diff --git a/net/proto/connection.go b/net/proto/connection.go index 4e1452932..615b5fb41 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -1520,6 +1520,7 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ continue } pi.connection = nc + pi.fl = lib.NewFlusher(nc) tail = t goto re @@ -3031,16 +3032,21 @@ func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compress } c.pool_mutex.RUnlock() - atomic.AddUint64(&c.messagesOut, 1) - atomic.AddUint64(&c.bytesOut, uint64(buf.Len())) - // TODO // add proxy, fragmentation support // c.transitOut++ // if buf.Len() < protoFragmentSize { - pi.fl.Write(buf.B) + bufLen := uint64(buf.Len()) + _, err := pi.fl.Write(buf.B) lib.ReleaseBuffer(buf) + if err != nil { + pi.connection.Close() + return err + } + + atomic.AddUint64(&c.messagesOut, 1) + atomic.AddUint64(&c.bytesOut, bufLen) return nil // } From 9307bb3c834f128dba849f6a2a818456f154875f Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 5 Mar 2026 20:19:43 +0100 Subject: [PATCH 038/122] add gen.RemoteNodeInfo.Reconnections - total number of pool item reconnections --- gen/network.go | 4 ++++ net/proto/connection.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/gen/network.go b/gen/network.go index 3798edbf8..b925a23ca 100644 --- a/gen/network.go +++ b/gen/network.go @@ -529,6 +529,10 @@ type RemoteNodeInfo struct { // TransitBytesOut is the total proxy transit bytes sent through this connection. // Only relevant if this connection is used as a proxy. TransitBytesOut uint64 + + // Reconnections is the total number of pool item reconnections. + // A non-zero value indicates connection instability. + Reconnections uint64 } // AcceptorOptions configures a network listener (acceptor) for incoming connections. diff --git a/net/proto/connection.go b/net/proto/connection.go index 615b5fb41..a139faf95 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -64,6 +64,8 @@ type connection struct { transitIn uint64 transitOut uint64 + reconnections uint64 + order uint32 terminated bool wg sync.WaitGroup @@ -120,6 +122,8 @@ func (c *connection) Info() gen.RemoteNodeInfo { TransitBytesIn: atomic.LoadUint64(&c.transitIn), TransitBytesOut: atomic.LoadUint64(&c.transitOut), + + Reconnections: atomic.LoadUint64(&c.reconnections), } return info } @@ -1522,6 +1526,7 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ pi.connection = nc pi.fl = lib.NewFlusher(nc) tail = t + atomic.AddUint64(&c.reconnections, 1) goto re } From 909f6f11d916f8cf39687333ebb0fd557d925a08 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 5 Mar 2026 22:18:29 +0100 Subject: [PATCH 039/122] update docs --- docs/extra-library/applications/mcp.md | 291 ++++++++++++++----------- 1 file changed, 158 insertions(+), 133 deletions(-) diff --git a/docs/extra-library/applications/mcp.md b/docs/extra-library/applications/mcp.md index 11caceef2..a0182c152 100644 --- a/docs/extra-library/applications/mcp.md +++ b/docs/extra-library/applications/mcp.md @@ -1,68 +1,82 @@ -# MCP +--- +description: AI-powered diagnostics for running Ergo nodes via Model Context Protocol +--- -The MCP application is a sidecar diagnostic tool for Ergo Framework nodes. It runs inside your node as a regular Ergo application and exposes 46 inspection tools via MCP (Model Context Protocol) over HTTP. AI agents like Claude Code connect to the endpoint and use these tools to diagnose performance bottlenecks, inspect processes, profile goroutines and heap, monitor metrics in real time, and trace issues across a cluster -- all without restarting or redeploying the node. +# MCP -The application has two deployment modes. An **entry point** node runs an HTTP listener that accepts MCP requests. An **agent** node has no HTTP listener but is fully accessible through the entry point via cluster proxy. This means a single HTTP endpoint gives access to every node in the cluster. +Diagnosing a distributed actor system is hard. The problem isn't a lack of data -- it's knowing what to look for. A node has hundreds of processes, dozens of connections, thousands of events flowing between them. Something is slow, but where? A process is stuck, but why? Memory is growing, but what's holding it? -The real power comes from combining MCP with other context the AI agent already has. When the agent can see your source code, inspect a live cluster in real time, and query your log storage (OpenSearch, Loki, CloudWatch) -- it connects the dots that no single tool can. It reads the actor implementation, checks its runtime state via MCP, correlates with error logs, and pinpoints the root cause. Source code explains intent. MCP shows what actually happens. Logs show the history. Together they eliminate guesswork. +Traditional monitoring collects predefined metrics at fixed intervals. You decide upfront what matters, build dashboards, and then interpret the data when something breaks. This works for known failure modes. It doesn't work when the failure is something you haven't anticipated -- and in distributed systems, the interesting failures are always unanticipated. -## Why MCP +MCP takes a different approach. Instead of predefined metrics, it exposes the full diagnostic surface of the node -- processes, applications, events, network, profiling, runtime -- as tools that an AI agent can call on demand. The agent decides what to inspect based on the symptom you describe. It runs diagnostic sequences, correlates findings across tools, narrows down root causes, and explains what it found. You describe the problem in words; the agent finds the answer in data. -Traditional monitoring tools (Prometheus, Grafana) collect predefined metrics at fixed intervals and display them on dashboards. You decide upfront what to track, configure scraping, build dashboards, and then interpret the data yourself when something goes wrong. +The real power comes from combination. The agent can see your source code, inspect the live cluster via MCP, and query your log storage -- all in the same conversation. It reads the actor implementation to understand intent, checks runtime state to see what actually happens, and correlates with error logs to see the history. Together these eliminate guesswork in a way no single tool can. -MCP takes a different approach. Instead of predefined metrics, it exposes the full diagnostic API of the node -- 46 tools covering processes, applications, events, network, runtime, and profiling. An AI agent decides what to inspect based on the symptom you describe. It runs diagnostic sequences, correlates findings across tools, and narrows down root causes interactively. +The application runs as a regular Ergo sidecar. Add it to your node's application list, and every process, connection, and event becomes inspectable -- without restarting, redeploying, or attaching a debugger. -This is particularly useful for: +## Two Deployment Modes -- **Source code + live cluster + logs** -- the agent reads your actor code to understand what a process should do, inspects it via MCP to see what it actually does, and checks logs to see what happened before. This combination is far more powerful than any of these tools in isolation. -- **Ad-hoc investigation** -- you don't need to have anticipated the problem. The agent explores the node's state dynamically. -- **Distributed tracing** -- the cluster proxy lets the agent inspect any node from a single entry point, following issues across node boundaries. -- **Real-time sampling** -- active samplers periodically call any tool and store results in a ring buffer. Passive samplers capture log streams and event publications as they happen. The agent reads collected data incrementally. -- **Deep profiling** -- goroutine stack traces per process PID (with `-tags=pprof`), heap profiling, runtime stats, all accessible through tool calls. +MCP has two modes: entry point and agent. -MCP complements rather than replaces traditional monitoring. Use Prometheus/Grafana for long-term trends and alerting, and MCP for interactive investigation when alerts fire. +An entry point node runs an HTTP listener that accepts MCP protocol requests. This is the node your AI client connects to. An agent node has no HTTP listener at all -- it's invisible from outside the cluster. But it runs the same diagnostic tools internally, and any entry point can reach it through cluster proxy. -## Adding to Your Node +In practice, you deploy one entry point and make everything else an agent: ```go import ( - "ergo.services/ergo" - "ergo.services/application/mcp" - "ergo.services/ergo/gen" + "ergo.services/ergo" + "ergo.services/application/mcp" + "ergo.services/ergo/gen" ) func main() { - opt := gen.NodeOptions{ - Applications: []gen.ApplicationBehavior{ - mcp.CreateApp(mcp.Options{ - Port: 9922, - }), - }, - } - node, err := ergo.StartNode("example@localhost", opt) - if err != nil { - panic(err) - } - node.Wait() + node, _ := ergo.StartNode("example@localhost", gen.NodeOptions{ + Applications: []gen.ApplicationBehavior{ + // Entry point -- the one HTTP endpoint for the entire cluster + mcp.CreateApp(mcp.Options{Port: 9922}), + }, + }) + node.Wait() +} +``` + +On every other node, the same application with no port: + +```go +// Agent mode -- no HTTP, but fully diagnosable via cluster proxy +mcp.CreateApp(mcp.Options{}) +``` + +The AI client connects to `http://entry-point:9922/mcp` and reaches any node in the cluster through that single endpoint. + +## Configuration + +```go +mcp.Options{ + Host: "localhost", // Listen address + Port: 9922, // HTTP port (0 = agent mode) + Token: "secret", // Bearer token (empty = no auth) + ReadOnly: false, // Disable action tools + AllowedTools: nil, // Tool whitelist (nil = all) + PoolSize: 5, // Worker processes + CertManager: nil, // TLS certificate manager + LogLevel: gen.LogLevelInfo, } ``` -The function `mcp.CreateApp` takes `mcp.Options` as an argument: +**Port** controls the deployment mode. A non-zero value starts an HTTP listener -- this is an entry point. Zero means agent mode: no listener, accessible only via cluster proxy from another node that has an entry point. + +**Token** enables Bearer token authentication. When set, every HTTP request must include `Authorization: Bearer `. When empty, no authentication is required. Agent mode nodes don't need a token -- they're accessed through the Ergo inter-node protocol, which has its own authentication via handshake cookies. -* **Port**: The port number for the HTTP endpoint (default: `0` which means agent mode -- no HTTP listener). -* **Host**: The interface name (default: `localhost`). -* **Token**: Bearer token for authentication. Empty string disables authentication. -* **ReadOnly**: When `true`, disables action tools (`send_message`, `call_process`, `send_exit`, `process_kill`). Useful for production nodes where you want inspection without the ability to modify state. -* **AllowedTools**: A whitelist of tool names. When set, only the listed tools are available. `nil` or empty means all tools are enabled (respecting `ReadOnly`). -* **PoolSize**: The number of worker processes that handle incoming requests (default: `5`). -* **LogLevel**: The logging level for the MCP application processes. +**ReadOnly** disables tools that modify state: `send_message`, `call_process`, `send_exit`, `process_kill`. Everything else -- inspection, profiling, sampling -- remains available. Use this on production nodes where you want full visibility without the ability to interfere. + +**AllowedTools** restricts the tool set to a whitelist. When set, only the named tools are available. This is finer-grained than ReadOnly -- you can, for example, allow `send_message` but not `process_kill`. When nil, all tools are enabled (respecting ReadOnly). ## Connecting a Client ### Claude Code ```bash -# Add the MCP server claude mcp add --transport http ergo http://localhost:9922/mcp # With authentication @@ -75,105 +89,121 @@ To allow all MCP tools without per-call permission prompts, add to `.claude/sett ```json { "permissions": { - "allow": [ - "mcp__ergo" - ] + "allow": ["mcp__ergo"] } } ``` -The prefix `mcp__ergo` matches the server name from the `claude mcp add` command. Once configured, the agent can call any of the 46 tools directly. - -### Other MCP Clients +### Other Clients The application implements MCP protocol version `2025-06-18` over HTTP. Any MCP-compatible client can connect by sending JSON-RPC 2.0 POST requests to `http://:/mcp`. -## What You Can Do +## How Cluster Proxy Works + +Every tool accepts a `node` parameter. When specified, the entry point node forwards the request to the target node via native Ergo inter-node protocol -- not HTTP. The target node's MCP worker executes the tool locally and returns the result through the same path. + +This works because of network transparency. The entry point calls `gen.ProcessID{Name: "mcp", Node: targetNode}` -- the framework establishes a connection if needed, routes the request, and delivers the response. You never need to explicitly connect to a node before querying it. If the registrar knows about the target node, the connection happens automatically. + +The `timeout` parameter (default 30 seconds, max 120) controls how long the entry point waits for a remote response. Most tools respond in milliseconds. But CPU profiling collects data for a requested duration before responding, and goroutine dumps on large nodes take time to serialize. For these, pass a higher timeout. + +If a remote tool call fails with "remote call failed", it usually means the target node doesn't have the MCP application running. All proxy calls require an MCP pool process on the target node -- agent mode is sufficient, but the application must be loaded and started. + +## Profiling Remote Nodes + +Profiling tools generate large output. A goroutine dump from a node with 500 goroutines can be megabytes of text. A heap profile with hundreds of allocation sites isn't much smaller. Push all of that through the proxy chain -- remote node, entry point, HTTP, JSON-RPC -- and you hit timeouts or transport limits. + +The solution is server-side filtering. All profiling tools accept `filter` and `exclude` parameters that reduce the output before it leaves the remote node. Instead of transferring 500 goroutine stacks and searching locally, you tell the remote node to return only the stacks that match: + +``` +pprof_goroutines node=backend@host debug=1 filter="orderHandler" limit=20 +``` + +The response header preserves the full picture: `goroutine profile: total 500, matched 3, showing 3`. You know the node has 500 goroutines, but only 3 matched your filter, and all 3 were returned. The agent can refine the filter, broaden it, or switch to a different angle -- each query is cheap because the heavy lifting happens on the remote node. -The 46 tools are organized into categories. You don't need to learn them -- the agent discovers available tools automatically via the MCP protocol. But understanding the categories helps you know what kinds of questions you can ask. +### CPU Profiling -Every tool accepts an optional `node` parameter for cluster proxy. When specified and the target is a different node, the request is forwarded via native Ergo inter-node protocol. +The `pprof_cpu` tool collects a CPU profile for a given duration and returns the top functions by CPU usage: -### Inspect node and processes +``` +pprof_cpu node=backend@host duration=5 exclude="runtime" limit=15 timeout=30 +``` + +The node samples CPU activity for 5 seconds, aggregates by function, filters out Go runtime internals, and returns the top 15 application functions with flat and cumulative percentages. The `timeout` should be higher than `duration` to account for collection and transfer time. + +### Heap Profiling + +The `pprof_heap` tool shows the top memory allocators with two columns: `inuse` (live objects currently in memory) and `alloc` (cumulative allocations over the node's lifetime). A function with low `inuse` but high `alloc` is churning memory -- allocating and releasing rapidly, putting pressure on the garbage collector. + +``` +pprof_heap node=backend@host filter="myapp" limit=20 +``` -The most common starting point. Ask the agent to show you what's happening on the node -- process counts, memory, CPU, running applications. Then drill into individual processes: who has the deepest mailbox, who consumes the most CPU, who was recently spawned. +### Goroutine Analysis -Example prompts: -- "Show me the overall health of the node" -- "Which processes have the deepest mailboxes right now?" -- "Find processes that were spawned in the last 30 seconds" -- "Show me the supervision tree under the order_sup process" -- "What's the state of process worker_3?" +The `pprof_goroutines` tool has two modes. Without `pid`, it returns all goroutines on the node -- use `filter` and `exclude` to narrow down. With `pid`, it returns the stack trace of a specific process's goroutine (requires `-tags=pprof`). -The `process_list` tool supports filtering (by application, behavior, state, name, numeric thresholds) and sorting (by mailbox depth, latency, running time, wakeups, drain ratio, etc.). This makes it the primary instrument for finding problematic processes. +Debug level controls the output format: `debug=1` groups goroutines by identical stack (compact summary with counts), `debug=2` shows individual goroutine traces with state and wait duration. -### Monitor applications and events +A sleeping process parks its goroutine -- it won't appear in the dump. To catch it, use an active sampler that polls until the process wakes up: -Check application lifecycle (loaded, running, stopped), inspect dependencies, and diagnose pub/sub event issues. The event tools detect common problems: events publishing to nobody, subscribers waiting for data that never comes, fanout overload. +``` +sample_start tool=pprof_goroutines arguments={"pid":""} interval_ms=300 count=1 max_errors=0 +``` -Example prompts: -- "Which applications are running? Any stopped?" -- "Show me events that have no subscribers" -- "Which events generate the most inter-node traffic?" -- "List all events owned by the order_handler process" +The sampler ignores the "goroutine not found" error (`max_errors=0`) and keeps polling every 300ms until it catches the process in a non-sleep state. -### Diagnose network and cluster +## Samplers -Inspect cluster connectivity, traffic between nodes, registrar state, and routes. Connect or disconnect nodes. The cluster proxy means you can inspect any node from a single entry point. +Snapshots show one moment. Trends show the story. Samplers bridge this gap by collecting data into ring buffers that the agent reads incrementally. -Example prompts: -- "Show me all nodes in the cluster and their status" -- "Is node backend@host connected? What's the traffic like?" -- "Connect to node worker@host and show its process list" -- "Check if the payment-service application is deployed across the cluster" +### Active Samplers -### Profile and debug +An active sampler periodically calls any MCP tool and stores the results. It's a generic periodic executor -- any tool with any arguments can be sampled. -Deep diagnostics: goroutine stack traces (per-process with `-tags=pprof`), heap profiling, runtime stats. Find deadlocks, goroutine leaks, memory pressure. +``` +sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10} interval_ms=5000 duration_sec=300 +``` -Example prompts: -- "Show me the goroutine dump, group by stack" -- "Get the stack trace of process order_handler" (requires `-tags=pprof`) -- "What's the heap profile? Who allocates the most?" -- "Are there any processes stuck in WaitResponse?" +This calls `process_list` every 5 seconds for 5 minutes, storing each result in a ring buffer. The agent reads with `sample_read sampler_id=` to get all buffered entries, or `sample_read sampler_id= since=5` to get only entries newer than sequence 5. -When a process is sleeping, its goroutine is parked and won't appear in the dump. The agent can use a sampler to poll until the process wakes up. +The `max_errors` parameter controls error tolerance. The default (0) means ignore all errors and keep retrying -- useful for polling rare conditions. A non-zero value stops the sampler after that many consecutive failures. -### Sample metrics over time +### Passive Samplers -Snapshots are useful but trends tell the real story. Active samplers periodically call any tool and store results in a ring buffer. Passive samplers capture log messages and event publications as they happen. +A passive sampler listens for events instead of polling. It captures log messages and event publications as they happen: -Example prompts: -- "Monitor the top 10 mailbox offenders for 5 minutes" -- "Track memory and GC stats every 5 seconds" -- "Capture error and panic logs for the next 2 minutes" -- "Subscribe to the order_events event and show me what gets published" -- "Try to catch the goroutine of process worker_5 -- it's usually sleeping" +``` +sample_listen log_levels=["warning","error"] duration_sec=120 +sample_listen event=order_events duration_sec=60 +sample_listen log_levels=["error"] event=order_events duration_sec=120 +``` -Active samplers are generic -- any tool can be sampled with any arguments. The `max_errors=0` parameter makes the sampler ignore errors and keep retrying, which is useful for polling rare conditions (like catching a sleeping process goroutine). All samplers are time-limited (default 60 seconds, maximum 1 hour). +Log capture and event subscription can be combined in a single sampler. -### Manage log levels +### Linger -Change log verbosity at runtime without restarting. Target the entire node, a specific process, or a meta process. +Every sampler has a `linger_sec` parameter (default 30). After the sampler completes -- duration expires, count reached, or max errors exceeded -- it stays alive for this many additional seconds so the agent can retrieve the collected data. Without linger, a sampler that runs for 10 seconds would terminate before the agent gets a chance to read the results. -Example prompts: -- "Set debug logging on the payment_handler process" -- "What's the current log level for the node?" -- "List all registered loggers" +The `sample_list` tool shows sampler status: `running`, `completed, lingering 25s`, or `completed`. The `sample_stop` tool terminates a sampler immediately, bypassing the linger period. -### Send messages and interact (action tools) +### What to Sample -When `ReadOnly` is not set, the agent can send messages to processes, make synchronous calls with typed payloads from the EDF registry, send exit signals, and kill processes. These tools require explicit user permission. +| Goal | Sampler | +|------|---------| +| Mailbox pressure trend | `sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10}` | +| Memory and GC trend | `sample_start tool=runtime_stats interval_ms=5000` | +| Error storm detection | `sample_listen log_levels=["error","panic"]` | +| Event traffic monitoring | `sample_listen event=` | +| Network health trend | `sample_start tool=network_nodes interval_ms=30000` | +| CPU hotspot sampling | `sample_start tool=pprof_goroutines arguments={"debug":1,"filter":"ProcessRun","exclude":"toolPprof","limit":20} interval_ms=500` | -Example prompts: -- "Send a StatusRequest to the worker_1 process and show the response" -- "What message types are registered in EDF?" -- "Gracefully stop the stuck_process with a shutdown signal" +## Typed Messages -The agent uses EDF type registry to construct typed Go structs from JSON. For example, if your application registers a `StatusRequest` type: +When `ReadOnly` is not set, the agent can send messages to processes and make synchronous calls using the EDF type registry. This isn't raw JSON injection -- the framework constructs real Go structs from the type information. + +If your application registers a type: ```go -// In your application code type StatusRequest struct { Verbose bool } @@ -183,60 +213,51 @@ func init() { } ``` -The agent can discover it with `message_types`, inspect its fields with `message_type_info`, and send it: - -``` -> Send a StatusRequest with Verbose=true to worker_1 +The agent discovers it with `message_types`, inspects its fields with `message_type_info`, and sends it with `call_process`. The process receives a real `StatusRequest{Verbose: true}` in its `HandleCall` -- not a map or raw bytes. -Agent calls: message_type_info(type_name="StatusRequest") - -> Fields: Verbose (bool) +This makes interactive debugging possible: the agent can call any process with any registered request type, inspect the response, and reason about the behavior. -Agent calls: call_process(to="worker_1", type_name="StatusRequest", request={"Verbose": true}) - -> Response: {"Status": "running", "Uptime": 3600} -``` +## Network Diagnostics -The process receives a real `StatusRequest{Verbose: true}` Go struct in its `HandleCall` -- not raw JSON. The EDF registry handles the reflection and construction. +The `network_ping` tool sends a request through the full network path -- flusher, TCP connection, remote MCP worker, response -- and measures the round-trip time. This is an end-to-end health check, not a TCP-level ping. If the flusher is broken, the connection pool is degraded, or the remote node is overloaded, the ping will reflect it. -## Cluster Proxy - -Every tool accepts a `node` parameter. When specified and the target differs from the local node, the request is forwarded to the remote node's MCP pool via native Ergo inter-node protocol -- not HTTP. The remote node must have the MCP application running, but agent mode (no HTTP) is sufficient. +``` +network_ping name=backend@host +→ ping backend@host: rtt 0.42ms +``` -This means you deploy one entry point node with HTTP and configure all other nodes as agents: +For deeper connection analysis, `network_node_info` shows per-connection statistics: messages in/out, bytes in/out, pool size, pool DSN (which side dialed), and a `Reconnections` counter that tracks how many times pool items have reconnected. A non-zero reconnection count indicates connection instability. -```go// Entry point node -- has HTTP listener -mcp.CreateApp(mcp.Options{Port: 9922}) +When investigating connection problems, always check both sides: -// Agent nodes -- no HTTP, accessible via cluster proxy -mcp.CreateApp(mcp.Options{}) +``` +network_node_info node=A name=B -- A's view of the connection to B +network_node_info node=B name=A -- B's view of the connection to A ``` -The agent connects to `http://entry-point:9922/mcp` and reaches any node in the cluster through the entry point. Connection between nodes happens through the standard Ergo network layer (registrar, static routes, or explicit connect). +Asymmetry between the two sides -- one sees thousands of messages out while the other sees one message in -- indicates data loss at the connection level. ## Build Tags -Two build tags enable additional diagnostic capabilities: +Two build tags enable additional diagnostic capabilities. Both add a small amount of overhead and should be enabled in staging and production builds where diagnostics matter. -**`-tags=pprof`** enables per-process goroutine stack traces. When built with this tag, actor goroutines are labeled with their process PID via `runtime/pprof` labels. The `pprof_goroutines` tool with `pid` parameter extracts the stack trace of a specific actor's goroutine. Without this tag, the `pid` parameter returns an error. +**`-tags=pprof`** enables the Go profiler and labels actor goroutines with their process PID. The labels appear in goroutine dumps as `{"pid":""}` for actors and `{"meta":"Alias#...", "role":"reader"}` for meta processes. The `pprof_goroutines` tool with `pid` parameter uses these labels to extract a specific actor's stack trace. Without this tag, the `pid` parameter returns an error. -**`-tags=latency`** enables mailbox latency measurement. The `process_list` tool gains `min_mailbox_latency_ms` filter and `mailbox_latency` sort field. Each process reports `MailboxLatency` -- how long the oldest message has been waiting in the mailbox. Without this tag, latency fields return -1. +This tag also starts a pprof HTTP endpoint at `localhost:9009/debug/pprof/` (configurable via `PPROF_HOST` and `PPROF_PORT` environment variables) for use with `go tool pprof`. -Both tags add a small amount of overhead. Enable them in staging and production builds where diagnostics matter. +**`-tags=latency`** enables mailbox latency measurement. Each mailbox queue tracks the age of its oldest unprocessed message. The `process_list` tool gains `min_mailbox_latency_ms` filter and `mailbox_latency` sort field. Without this tag, latency fields return -1. ## Relationship to Metrics Actor -The [Metrics](../actors/metrics.md) actor collects predefined metrics into Prometheus format for scraping by external monitoring systems. The MCP application provides the same underlying data (it reads from `ProcessRangeShortInfo`, `NodeInfo`, `EventRangeInfo` -- the same sources) but exposes it interactively through tool calls. +The [Metrics](../actors/metrics.md) actor collects predefined metrics into Prometheus format for scraping. MCP reads from the same underlying data sources -- `ProcessRangeShortInfo`, `NodeInfo`, `EventRangeInfo` -- but exposes them interactively. -Active samplers can replicate what the metrics actor does -- `sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10}` is equivalent to the `ergo_mailbox_depth_top` Prometheus metric. The key difference is that MCP samplers are on-demand and agent-driven, while Prometheus metrics are always-on and scraper-driven. +Active samplers can replicate any Prometheus metric: `sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10}` is equivalent to `ergo_mailbox_depth_top`. The difference is that MCP samplers are on-demand and agent-driven, while Prometheus metrics are always-on and scraper-driven. -Use the metrics actor when you need long-term time-series storage, alerting rules, and Grafana dashboards. Use MCP when you need interactive investigation, ad-hoc queries, and AI-assisted diagnostics. +Use the metrics actor for long-term trends, alerting, and Grafana dashboards. Use MCP for interactive investigation when alerts fire or when you need to explore something unexpected. ## Agent and Skill for Claude Code -A ready-to-use Claude Code agent and skill are available at [github.com/ergo-services/claude](https://github.com/ergo-services/claude): - -* **ergo-devops agent** (`claude/agents/ergo-devops.md`) -- interactive diagnostics agent that connects to a running node via MCP and runs diagnostic sequences. Contains playbooks for performance bottlenecks, process leaks, restart loops, zombie processes, memory growth, network issues, event system problems, goroutine investigation, and cluster health checks. Trigger it by describing a symptom ("why is it slow", "check the cluster", "find process leak"). - -* **ergo-devops skill** (`claude/skills/ergo-devops/SKILL.md`) -- compact reference with the same playbooks in recipe format, pattern matching tables, and sampler quick reference. Load it via `/ergo-devops` in Claude Code for quick lookup without starting a full investigation. +A ready-to-use diagnostic agent and skill are available at [github.com/ergo-services/claude](https://github.com/ergo-services/claude). The agent contains playbooks for common scenarios: performance bottlenecks, process leaks, restart loops, zombie processes, memory growth, network issues, event system problems, goroutine investigation, and cluster health checks. Trigger it by describing a symptom -- "why is it slow", "check the cluster", "find the process leak" -- and it runs the appropriate diagnostic sequence. Install by symlinking into `~/.claude/`: @@ -245,3 +266,7 @@ cd ergo.services/claude ln -sf $(pwd)/agents/ergo-devops.md ~/.claude/agents/ ln -sf $(pwd)/skills/ergo-devops ~/.claude/skills/ ``` + +## Full Tool Reference + +The complete list of 48 tools with parameters and descriptions is in the [MCP application README](https://github.com/ergo-services/application/blob/master/mcp/README.md). From 3ae17bf18ea9dac9800e3796989604d3a1a4ca0f Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 5 Mar 2026 22:49:23 +0100 Subject: [PATCH 040/122] update docs --- docs/extra-library/applications/mcp.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/extra-library/applications/mcp.md b/docs/extra-library/applications/mcp.md index a0182c152..099124349 100644 --- a/docs/extra-library/applications/mcp.md +++ b/docs/extra-library/applications/mcp.md @@ -79,6 +79,9 @@ mcp.Options{ ```bash claude mcp add --transport http ergo http://localhost:9922/mcp +# Available from any directory (user scope) +claude mcp add --transport http ergo --scope user http://localhost:9922/mcp + # With authentication claude mcp add --transport http ergo http://localhost:9922/mcp \ -H "Authorization: Bearer my-secret-token" From 02f1fcc15877be1cf87137bb33a7fe2711b11e7e Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 5 Mar 2026 22:57:03 +0100 Subject: [PATCH 041/122] update docs --- docs/extra-library/applications/mcp.md | 62 +++++++++++++------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/extra-library/applications/mcp.md b/docs/extra-library/applications/mcp.md index 099124349..510a8955b 100644 --- a/docs/extra-library/applications/mcp.md +++ b/docs/extra-library/applications/mcp.md @@ -4,21 +4,21 @@ description: AI-powered diagnostics for running Ergo nodes via Model Context Pro # MCP -Diagnosing a distributed actor system is hard. The problem isn't a lack of data -- it's knowing what to look for. A node has hundreds of processes, dozens of connections, thousands of events flowing between them. Something is slow, but where? A process is stuck, but why? Memory is growing, but what's holding it? +Diagnosing a distributed actor system is hard. The problem isn't a lack of data - it's knowing what to look for. A node has hundreds of processes, dozens of connections, thousands of events flowing between them. Something is slow, but where? A process is stuck, but why? Memory is growing, but what's holding it? -Traditional monitoring collects predefined metrics at fixed intervals. You decide upfront what matters, build dashboards, and then interpret the data when something breaks. This works for known failure modes. It doesn't work when the failure is something you haven't anticipated -- and in distributed systems, the interesting failures are always unanticipated. +Traditional monitoring collects predefined metrics at fixed intervals. You decide upfront what matters, build dashboards, and then interpret the data when something breaks. This works for known failure modes. It doesn't work when the failure is something you haven't anticipated - and in distributed systems, the interesting failures are always unanticipated. -MCP takes a different approach. Instead of predefined metrics, it exposes the full diagnostic surface of the node -- processes, applications, events, network, profiling, runtime -- as tools that an AI agent can call on demand. The agent decides what to inspect based on the symptom you describe. It runs diagnostic sequences, correlates findings across tools, narrows down root causes, and explains what it found. You describe the problem in words; the agent finds the answer in data. +MCP takes a different approach. Instead of predefined metrics, it exposes the full diagnostic surface of the node - processes, applications, events, network, profiling, runtime - as tools that an AI agent can call on demand. The agent decides what to inspect based on the symptom you describe. It runs diagnostic sequences, correlates findings across tools, narrows down root causes, and explains what it found. You describe the problem in words; the agent finds the answer in data. -The real power comes from combination. The agent can see your source code, inspect the live cluster via MCP, and query your log storage -- all in the same conversation. It reads the actor implementation to understand intent, checks runtime state to see what actually happens, and correlates with error logs to see the history. Together these eliminate guesswork in a way no single tool can. +The real power comes from combination. The agent can see your source code, inspect the live cluster via MCP, and query your log storage - all in the same conversation. It reads the actor implementation to understand intent, checks runtime state to see what actually happens, and correlates with error logs to see the history. Together these eliminate guesswork in a way no single tool can. -The application runs as a regular Ergo sidecar. Add it to your node's application list, and every process, connection, and event becomes inspectable -- without restarting, redeploying, or attaching a debugger. +The application runs as a regular Ergo sidecar. Add it to your node's application list, and every process, connection, and event becomes inspectable - without restarting, redeploying, or attaching a debugger. ## Two Deployment Modes MCP has two modes: entry point and agent. -An entry point node runs an HTTP listener that accepts MCP protocol requests. This is the node your AI client connects to. An agent node has no HTTP listener at all -- it's invisible from outside the cluster. But it runs the same diagnostic tools internally, and any entry point can reach it through cluster proxy. +An entry point node runs an HTTP listener that accepts MCP protocol requests. This is the node your AI client connects to. An agent node has no HTTP listener at all - it's invisible from outside the cluster. But it runs the same diagnostic tools internally, and any entry point can reach it through cluster proxy. In practice, you deploy one entry point and make everything else an agent: @@ -32,7 +32,7 @@ import ( func main() { node, _ := ergo.StartNode("example@localhost", gen.NodeOptions{ Applications: []gen.ApplicationBehavior{ - // Entry point -- the one HTTP endpoint for the entire cluster + // Entry point - the one HTTP endpoint for the entire cluster mcp.CreateApp(mcp.Options{Port: 9922}), }, }) @@ -43,7 +43,7 @@ func main() { On every other node, the same application with no port: ```go -// Agent mode -- no HTTP, but fully diagnosable via cluster proxy +// Agent mode - no HTTP, but fully diagnosable via cluster proxy mcp.CreateApp(mcp.Options{}) ``` @@ -64,13 +64,13 @@ mcp.Options{ } ``` -**Port** controls the deployment mode. A non-zero value starts an HTTP listener -- this is an entry point. Zero means agent mode: no listener, accessible only via cluster proxy from another node that has an entry point. +**Port** controls the deployment mode. A non-zero value starts an HTTP listener - this is an entry point. Zero means agent mode: no listener, accessible only via cluster proxy from another node that has an entry point. -**Token** enables Bearer token authentication. When set, every HTTP request must include `Authorization: Bearer `. When empty, no authentication is required. Agent mode nodes don't need a token -- they're accessed through the Ergo inter-node protocol, which has its own authentication via handshake cookies. +**Token** enables Bearer token authentication. When set, every HTTP request must include `Authorization: Bearer `. When empty, no authentication is required. Agent mode nodes don't need a token - they're accessed through the Ergo inter-node protocol, which has its own authentication via handshake cookies. -**ReadOnly** disables tools that modify state: `send_message`, `call_process`, `send_exit`, `process_kill`. Everything else -- inspection, profiling, sampling -- remains available. Use this on production nodes where you want full visibility without the ability to interfere. +**ReadOnly** disables tools that modify state: `send_message`, `call_process`, `send_exit`, `process_kill`. Everything else - inspection, profiling, sampling - remains available. Use this on production nodes where you want full visibility without the ability to interfere. -**AllowedTools** restricts the tool set to a whitelist. When set, only the named tools are available. This is finer-grained than ReadOnly -- you can, for example, allow `send_message` but not `process_kill`. When nil, all tools are enabled (respecting ReadOnly). +**AllowedTools** restricts the tool set to a whitelist. When set, only the named tools are available. This is finer-grained than ReadOnly - you can, for example, allow `send_message` but not `process_kill`. When nil, all tools are enabled (respecting ReadOnly). ## Connecting a Client @@ -103,17 +103,17 @@ The application implements MCP protocol version `2025-06-18` over HTTP. Any MCP- ## How Cluster Proxy Works -Every tool accepts a `node` parameter. When specified, the entry point node forwards the request to the target node via native Ergo inter-node protocol -- not HTTP. The target node's MCP worker executes the tool locally and returns the result through the same path. +Every tool accepts a `node` parameter. When specified, the entry point node forwards the request to the target node via native Ergo inter-node protocol - not HTTP. The target node's MCP worker executes the tool locally and returns the result through the same path. -This works because of network transparency. The entry point calls `gen.ProcessID{Name: "mcp", Node: targetNode}` -- the framework establishes a connection if needed, routes the request, and delivers the response. You never need to explicitly connect to a node before querying it. If the registrar knows about the target node, the connection happens automatically. +This works because of network transparency. The entry point calls `gen.ProcessID{Name: "mcp", Node: targetNode}` - the framework establishes a connection if needed, routes the request, and delivers the response. You never need to explicitly connect to a node before querying it. If the registrar knows about the target node, the connection happens automatically. The `timeout` parameter (default 30 seconds, max 120) controls how long the entry point waits for a remote response. Most tools respond in milliseconds. But CPU profiling collects data for a requested duration before responding, and goroutine dumps on large nodes take time to serialize. For these, pass a higher timeout. -If a remote tool call fails with "remote call failed", it usually means the target node doesn't have the MCP application running. All proxy calls require an MCP pool process on the target node -- agent mode is sufficient, but the application must be loaded and started. +If a remote tool call fails with "remote call failed", it usually means the target node doesn't have the MCP application running. All proxy calls require an MCP pool process on the target node - agent mode is sufficient, but the application must be loaded and started. ## Profiling Remote Nodes -Profiling tools generate large output. A goroutine dump from a node with 500 goroutines can be megabytes of text. A heap profile with hundreds of allocation sites isn't much smaller. Push all of that through the proxy chain -- remote node, entry point, HTTP, JSON-RPC -- and you hit timeouts or transport limits. +Profiling tools generate large output. A goroutine dump from a node with 500 goroutines can be megabytes of text. A heap profile with hundreds of allocation sites isn't much smaller. Push all of that through the proxy chain - remote node, entry point, HTTP, JSON-RPC - and you hit timeouts or transport limits. The solution is server-side filtering. All profiling tools accept `filter` and `exclude` parameters that reduce the output before it leaves the remote node. Instead of transferring 500 goroutine stacks and searching locally, you tell the remote node to return only the stacks that match: @@ -121,7 +121,7 @@ The solution is server-side filtering. All profiling tools accept `filter` and ` pprof_goroutines node=backend@host debug=1 filter="orderHandler" limit=20 ``` -The response header preserves the full picture: `goroutine profile: total 500, matched 3, showing 3`. You know the node has 500 goroutines, but only 3 matched your filter, and all 3 were returned. The agent can refine the filter, broaden it, or switch to a different angle -- each query is cheap because the heavy lifting happens on the remote node. +The response header preserves the full picture: `goroutine profile: total 500, matched 3, showing 3`. You know the node has 500 goroutines, but only 3 matched your filter, and all 3 were returned. The agent can refine the filter, broaden it, or switch to a different angle - each query is cheap because the heavy lifting happens on the remote node. ### CPU Profiling @@ -135,7 +135,7 @@ The node samples CPU activity for 5 seconds, aggregates by function, filters out ### Heap Profiling -The `pprof_heap` tool shows the top memory allocators with two columns: `inuse` (live objects currently in memory) and `alloc` (cumulative allocations over the node's lifetime). A function with low `inuse` but high `alloc` is churning memory -- allocating and releasing rapidly, putting pressure on the garbage collector. +The `pprof_heap` tool shows the top memory allocators with two columns: `inuse` (live objects currently in memory) and `alloc` (cumulative allocations over the node's lifetime). A function with low `inuse` but high `alloc` is churning memory - allocating and releasing rapidly, putting pressure on the garbage collector. ``` pprof_heap node=backend@host filter="myapp" limit=20 @@ -143,11 +143,11 @@ pprof_heap node=backend@host filter="myapp" limit=20 ### Goroutine Analysis -The `pprof_goroutines` tool has two modes. Without `pid`, it returns all goroutines on the node -- use `filter` and `exclude` to narrow down. With `pid`, it returns the stack trace of a specific process's goroutine (requires `-tags=pprof`). +The `pprof_goroutines` tool has two modes. Without `pid`, it returns all goroutines on the node - use `filter` and `exclude` to narrow down. With `pid`, it returns the stack trace of a specific process's goroutine (requires `-tags=pprof`). Debug level controls the output format: `debug=1` groups goroutines by identical stack (compact summary with counts), `debug=2` shows individual goroutine traces with state and wait duration. -A sleeping process parks its goroutine -- it won't appear in the dump. To catch it, use an active sampler that polls until the process wakes up: +A sleeping process parks its goroutine - it won't appear in the dump. To catch it, use an active sampler that polls until the process wakes up: ``` sample_start tool=pprof_goroutines arguments={"pid":""} interval_ms=300 count=1 max_errors=0 @@ -161,7 +161,7 @@ Snapshots show one moment. Trends show the story. Samplers bridge this gap by co ### Active Samplers -An active sampler periodically calls any MCP tool and stores the results. It's a generic periodic executor -- any tool with any arguments can be sampled. +An active sampler periodically calls any MCP tool and stores the results. It's a generic periodic executor - any tool with any arguments can be sampled. ``` sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10} interval_ms=5000 duration_sec=300 @@ -169,7 +169,7 @@ sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10} interv This calls `process_list` every 5 seconds for 5 minutes, storing each result in a ring buffer. The agent reads with `sample_read sampler_id=` to get all buffered entries, or `sample_read sampler_id= since=5` to get only entries newer than sequence 5. -The `max_errors` parameter controls error tolerance. The default (0) means ignore all errors and keep retrying -- useful for polling rare conditions. A non-zero value stops the sampler after that many consecutive failures. +The `max_errors` parameter controls error tolerance. The default (0) means ignore all errors and keep retrying - useful for polling rare conditions. A non-zero value stops the sampler after that many consecutive failures. ### Passive Samplers @@ -185,7 +185,7 @@ Log capture and event subscription can be combined in a single sampler. ### Linger -Every sampler has a `linger_sec` parameter (default 30). After the sampler completes -- duration expires, count reached, or max errors exceeded -- it stays alive for this many additional seconds so the agent can retrieve the collected data. Without linger, a sampler that runs for 10 seconds would terminate before the agent gets a chance to read the results. +Every sampler has a `linger_sec` parameter (default 30). After the sampler completes - duration expires, count reached, or max errors exceeded - it stays alive for this many additional seconds so the agent can retrieve the collected data. Without linger, a sampler that runs for 10 seconds would terminate before the agent gets a chance to read the results. The `sample_list` tool shows sampler status: `running`, `completed, lingering 25s`, or `completed`. The `sample_stop` tool terminates a sampler immediately, bypassing the linger period. @@ -202,7 +202,7 @@ The `sample_list` tool shows sampler status: `running`, `completed, lingering 25 ## Typed Messages -When `ReadOnly` is not set, the agent can send messages to processes and make synchronous calls using the EDF type registry. This isn't raw JSON injection -- the framework constructs real Go structs from the type information. +When `ReadOnly` is not set, the agent can send messages to processes and make synchronous calls using the EDF type registry. This isn't raw JSON injection - the framework constructs real Go structs from the type information. If your application registers a type: @@ -216,13 +216,13 @@ func init() { } ``` -The agent discovers it with `message_types`, inspects its fields with `message_type_info`, and sends it with `call_process`. The process receives a real `StatusRequest{Verbose: true}` in its `HandleCall` -- not a map or raw bytes. +The agent discovers it with `message_types`, inspects its fields with `message_type_info`, and sends it with `call_process`. The process receives a real `StatusRequest{Verbose: true}` in its `HandleCall` - not a map or raw bytes. This makes interactive debugging possible: the agent can call any process with any registered request type, inspect the response, and reason about the behavior. ## Network Diagnostics -The `network_ping` tool sends a request through the full network path -- flusher, TCP connection, remote MCP worker, response -- and measures the round-trip time. This is an end-to-end health check, not a TCP-level ping. If the flusher is broken, the connection pool is degraded, or the remote node is overloaded, the ping will reflect it. +The `network_ping` tool sends a request through the full network path - flusher, TCP connection, remote MCP worker, response - and measures the round-trip time. This is an end-to-end health check, not a TCP-level ping. If the flusher is broken, the connection pool is degraded, or the remote node is overloaded, the ping will reflect it. ``` network_ping name=backend@host @@ -234,11 +234,11 @@ For deeper connection analysis, `network_node_info` shows per-connection statist When investigating connection problems, always check both sides: ``` -network_node_info node=A name=B -- A's view of the connection to B -network_node_info node=B name=A -- B's view of the connection to A +network_node_info node=A name=B # A's view of the connection to B +network_node_info node=B name=A # B's view of the connection to A ``` -Asymmetry between the two sides -- one sees thousands of messages out while the other sees one message in -- indicates data loss at the connection level. +Asymmetry between the two sides - one sees thousands of messages out while the other sees one message in - indicates data loss at the connection level. ## Build Tags @@ -252,7 +252,7 @@ This tag also starts a pprof HTTP endpoint at `localhost:9009/debug/pprof/` (con ## Relationship to Metrics Actor -The [Metrics](../actors/metrics.md) actor collects predefined metrics into Prometheus format for scraping. MCP reads from the same underlying data sources -- `ProcessRangeShortInfo`, `NodeInfo`, `EventRangeInfo` -- but exposes them interactively. +The [Metrics](../actors/metrics.md) actor collects predefined metrics into Prometheus format for scraping. MCP reads from the same underlying data sources - `ProcessRangeShortInfo`, `NodeInfo`, `EventRangeInfo` - but exposes them interactively. Active samplers can replicate any Prometheus metric: `sample_start tool=process_list arguments={"sort_by":"mailbox","limit":10}` is equivalent to `ergo_mailbox_depth_top`. The difference is that MCP samplers are on-demand and agent-driven, while Prometheus metrics are always-on and scraper-driven. @@ -260,7 +260,7 @@ Use the metrics actor for long-term trends, alerting, and Grafana dashboards. Us ## Agent and Skill for Claude Code -A ready-to-use diagnostic agent and skill are available at [github.com/ergo-services/claude](https://github.com/ergo-services/claude). The agent contains playbooks for common scenarios: performance bottlenecks, process leaks, restart loops, zombie processes, memory growth, network issues, event system problems, goroutine investigation, and cluster health checks. Trigger it by describing a symptom -- "why is it slow", "check the cluster", "find the process leak" -- and it runs the appropriate diagnostic sequence. +A ready-to-use diagnostic agent and skill are available at [github.com/ergo-services/claude](https://github.com/ergo-services/claude). The agent contains playbooks for common scenarios: performance bottlenecks, process leaks, restart loops, zombie processes, memory growth, network issues, event system problems, goroutine investigation, and cluster health checks. Trigger it by describing a symptom - "why is it slow", "check the cluster", "find the process leak" - and it runs the appropriate diagnostic sequence. Install by symlinking into `~/.claude/`: From 00845280714d5e5dc408ff42cbf7eae4039251ec Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 6 Mar 2026 12:37:31 +0100 Subject: [PATCH 042/122] update docs --- docs/extra-library/actors/metrics.md | 28 +++++++++++++++ docs/extra-library/applications/radar.md | 45 ++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 67c4cb737..56267d343 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -217,6 +217,34 @@ func (m *AppMetrics) HandleMessage(from gen.PID, message any) error { } ``` +### Custom Top-N Metrics + +Top-N metrics track the N highest (or lowest) values observed during each collection cycle. Unlike gauges or counters, a top-N metric accumulates observations and periodically flushes only the top entries to Prometheus as a GaugeVec. This is useful when you want to identify the most active, slowest, or largest items out of many -- without creating a separate time series for each one. + +Each top-N metric is managed by a dedicated actor spawned under a SimpleOneForOne supervisor. Registration creates this actor; observations are sent to it asynchronously. On each flush interval the actor writes the current top-N entries to Prometheus and resets for the next cycle. + +```go +// Register a top-N metric (sync Call, returns error) +// TopNMax keeps the N largest values; TopNMin keeps the N smallest +metrics.RegisterTopN(w, "topn_supervisor_name", "slowest_queries", "Slowest DB queries", + 10, metrics.TopNMax, []string{"query", "table"}) + +// Observe values (async Send) +metrics.TopNObserve(w, gen.Atom("radar_topn_slowest_queries"), 0.250, []string{"SELECT ...", "users"}) +metrics.TopNObserve(w, gen.Atom("radar_topn_slowest_queries"), 1.100, []string{"JOIN ...", "orders"}) +``` + +The `to` parameter in `RegisterTopN` is the name of the supervisor managing top-N actors. The `to` parameter in `TopNObserve` is the actor name -- by convention `"radar_topn_" + metricName`. + +Ordering modes: + +- `metrics.TopNMax` -- keeps the N largest values (e.g., slowest queries, busiest actors, highest memory usage) +- `metrics.TopNMin` -- keeps the N smallest values (e.g., lowest latency, least active processes) + +When the process that registered a top-N metric terminates, the actor automatically cleans up and unregisters its GaugeVec from Prometheus. + +When used through the [Radar](../applications/radar.md) application, the supervisor is already wired in and you use `radar.RegisterTopN` / `radar.TopNObserve` helpers instead. + ### Shared Mode A single metrics actor processes messages sequentially. Under high throughput, its mailbox becomes a bottleneck. Shared mode lets multiple metrics actor instances share the same Prometheus registry: diff --git a/docs/extra-library/applications/radar.md b/docs/extra-library/applications/radar.md index 181c53615..d8eaf9b60 100644 --- a/docs/extra-library/applications/radar.md +++ b/docs/extra-library/applications/radar.md @@ -197,6 +197,51 @@ radar.HistogramObserve(process, name, value, labels) For a detailed explanation of metric types, the Grafana dashboard, and advanced usage (embedding, shared mode), see the [Metrics](../actors/metrics.md) actor documentation. +## Top-N Metrics + +Top-N metrics track the N highest (or lowest) values observed during each collection cycle and flush them to Prometheus as a GaugeVec. This is useful when you want to identify outliers -- slowest queries, busiest workers, largest payloads -- without creating a time series per item. + +### Registering and Observing + +```go +func (w *QueryTracker) Init(args ...any) error { + // Keep the 10 slowest queries each cycle + radar.RegisterTopN(w, "slowest_queries", "Slowest DB queries", + 10, radar.TopNMax, []string{"query", "table"}) + return nil +} + +func (w *QueryTracker) HandleMessage(from gen.PID, message any) error { + switch msg := message.(type) { + case queryCompleted: + radar.TopNObserve(w, "slowest_queries", msg.Duration.Seconds(), + []string{msg.SQL, msg.Table}) + } + return nil +} +``` + +Registration is synchronous (returns error). Observations are asynchronous (fire-and-forget). Each top-N metric is managed by a dedicated actor that accumulates observations and flushes the top entries to Prometheus on the same interval as base metrics collection. + +### Ordering Modes + +- `radar.TopNMax` -- keeps the N largest values (e.g., slowest queries, busiest actors, highest memory) +- `radar.TopNMin` -- keeps the N smallest values (e.g., lowest latency, least active processes) + +### Automatic Cleanup + +When the process that registered a top-N metric terminates, the metric actor cleans up and unregisters from Prometheus. No explicit teardown needed. + +### Helper Functions + +```go +// Registration (sync Call, returns error) +radar.RegisterTopN(process, name, help, topN, order, labels) + +// Observation (async Send, fire-and-forget) +radar.TopNObserve(process, name, value, labels) +``` + ## Common Patterns ### Database Connection Pool From 2294795121155d8d644049d7ba8f9788c00285ae Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 9 Mar 2026 17:55:45 +0100 Subject: [PATCH 043/122] add SoftwareKeepalive feature --- CHANGELOG.md | 2 ++ README.md | 4 +++ docs/networking/network-stack.md | 34 +++++++++++++++++++- gen/default.go | 4 +++ gen/network.go | 26 +++++++++++++++ lib/flusher.go | 50 ++++++++++++++++++++--------- net/handshake/types.go | 5 ++- net/proto/connection.go | 55 ++++++++++++++++++++++++++++---- net/proto/enp.go | 18 +++++++++++ net/proto/types.go | 3 ++ node/acceptor.go | 2 ++ node/network.go | 43 +++++++++++++++++++++++-- 12 files changed, 220 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8dd41dc5..22d7ea314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed **self-send message counter** - `messagesOut` now incremented for self-sends * Fixed **simultaneous connect dead loop** - two nodes dialing each other at the same time no longer cause infinite retry loops. Deterministic connection IDs and Erlang-style collision detection (`EnableSimultaneousConnect` flag) ensure exactly one connection per pair. Fixed related connection leaks * Fixed **silent data loss on connection pool write failure** - a transient write error could permanently break a pool item's write path without detection, causing all subsequent messages to be silently dropped while the connection appeared healthy +* Added **software keepalive** for inter-node connections. Application-level heartbeat detects silent failures that TCP keepalive cannot: stuck processes, broken flushers, goroutine starvation. Each side advertises its period during handshake (8 bits in `NetworkFlags`); receiver uses peer's period for timeout. Enabled by default (15s period, 3 misses, 45s timeout). Configure via `NetworkFlags.EnableSoftwareKeepAlive` and `NetworkOptions.SoftwareKeepAliveMisses`. See [Network Stack](https://docs.ergo.services/networking/network-stack#software-keepalive) documentation +* Added **handshake deadline** (5s) to prevent hung handshakes from blocking connection goroutines indefinitely #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index 5ca40681d..69e3995fc 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,10 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Fixed **silent data loss on connection pool write failure** - a transient write error could permanently break a pool item's write path without detection, causing all subsequent messages to be silently dropped while the connection appeared healthy +* Added **software keepalive** for inter-node connections - application-level heartbeat that detects silent failures invisible to TCP keepalive. Enabled by default (15s period, 3 misses, 45s timeout). See [Network Stack](https://docs.ergo.services/networking/network-stack#software-keepalive) documentation + +* Added **handshake deadline** (5s) to prevent hung handshakes from blocking connection goroutines indefinitely + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at diff --git a/docs/networking/network-stack.md b/docs/networking/network-stack.md index 6a456de45..e3c3a8820 100644 --- a/docs/networking/network-stack.md +++ b/docs/networking/network-stack.md @@ -105,6 +105,36 @@ The dialing node opens additional TCP connections using a shortened join handsha Multiple connections enable parallel message delivery. Each message goes to a connection based on the sender's identity, and the receiving side creates multiple receive queues per TCP connection for concurrent processing. This two-level mechanism -- sender-side link selection and receiver-side queue routing -- preserves per-sender message ordering while enabling parallelism across different senders. For details on how ordering works, including the `KeepNetworkOrder` flag and when to disable it, see [Message Ordering](network-transparency.md#message-ordering). +### Software Keepalive + +*Introduced in v3.3.0.* + +TCP keepalive operates at the OS level - it detects hard network failures like unplugged cables or crashed hosts. But it can't detect application-level problems: a stuck process that stopped reading from a connection, a flusher that failed silently, a goroutine that never got scheduled. The connection looks alive to TCP while no useful data flows. + +Software keepalive works at the protocol level. When a connection pool item has nothing to send, its flusher periodically writes a small keepalive packet. The receiving side expects these packets and sets a read deadline based on the sender's advertised period. If nothing arrives - no real messages and no keepalive packets - the deadline fires and the connection is terminated. + +Each side advertises its keepalive period during handshake. This allows asymmetric configuration: a node in a reliable datacenter might send keepalive every 15 seconds, while a node on an unstable network might send every 5 seconds. The receiver calculates its deadline from the sender's period, not its own. + +```go +node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ + Network: gen.NetworkOptions{ + Flags: gen.NetworkFlags{ + // ... other flags ... + EnableSoftwareKeepAlive: 15, // send keepalive every 15 seconds when idle + }, + SoftwareKeepAliveMisses: 3, // tolerate 3 missed keepalives before disconnect + }, +}) +``` + +The timeout calculation uses the remote node's period, not the local one. If the remote node advertises a 15-second period and you configure 3 misses, the connection is considered dead after 45 seconds of silence. Real messages reset the deadline just like keepalive packets do - on a busy connection, keepalive is never sent because regular traffic keeps the deadline from expiring. + +When a keepalive timeout fires on any pool item, the entire connection is terminated - not just the affected TCP link. A single unresponsive link is strong evidence that the whole network path to the remote node is down. This triggers the standard cleanup flow: monitors receive `MessageDown`, links receive `MessageExit`, and the connection is removed from the node's connection map. + +Software keepalive is enabled by default (15-second period, 3 misses, 45-second timeout). Set `EnableSoftwareKeepAlive` to 0 to disable it. Acceptors and routes can override the misses count; zero inherits from `NetworkOptions`. + +Both sides must have keepalive enabled for the feature to activate. If either side advertises period 0, the connection falls back to TCP-only keepalive with infinite read deadline - neither side sends keepalive packets and neither side sets read deadlines. This means a single node with keepalive disabled in a cluster removes protection for all its connections, not just its own. During a rolling upgrade from older nodes (which don't support the feature) to newer ones, connections between old and new nodes will not have software keepalive until both sides are upgraded. + ## Message Encoding and Transmission Once a connection exists, messages flow through encoding and framing. @@ -156,7 +186,9 @@ node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ EnableRemoteSpawn: true, EnableRemoteApplicationStart: true, EnableImportantDelivery: true, + EnableSoftwareKeepAlive: 15, // seconds, 0 to disable }, + SoftwareKeepAliveMisses: 3, // tolerate 3 missed keepalives Acceptors: []gen.AcceptorOptions{ { Port: 15000, @@ -174,7 +206,7 @@ node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ **MaxMessageSize** - Maximum incoming message size. Protects against memory exhaustion. Default unlimited (fine for trusted clusters). -**Flags** - Control capabilities. Remote nodes learn your flags during handshake and can only use features you've enabled. `EnableRemoteSpawn` allows spawning (with explicit permission per process). `EnableImportantDelivery` enables delivery confirmation. +**Flags** - Control capabilities. Remote nodes learn your flags during handshake and can only use features you've enabled. `EnableRemoteSpawn` allows spawning (with explicit permission per process). `EnableImportantDelivery` enables delivery confirmation. `EnableSoftwareKeepAlive` sets the keepalive period in seconds (see [Software Keepalive](#software-keepalive)). **Acceptors** - Define listeners for incoming connections. Multiple acceptors on different ports are supported. Each can have its own cookie, TLS, and protocol. diff --git a/gen/default.go b/gen/default.go index 0cd3b4150..7809ca0c7 100644 --- a/gen/default.go +++ b/gen/default.go @@ -25,6 +25,9 @@ var ( DefaultTCPBufferSize int = 65535 DefaultPort uint16 = 11144 + DefaultHandshakeTimeout time.Duration = 5 * time.Second + DefaultSoftwareKeepAliveMisses int = 3 + DefaultNetworkFlags = NetworkFlags{ Enable: true, EnableRemoteSpawn: true, @@ -34,6 +37,7 @@ var ( EnableProxyAccept: true, EnableImportantDelivery: true, EnableSimultaneousConnect: true, + EnableSoftwareKeepAlive: 15, // seconds } DefaultNetworkProxyFlags = NetworkProxyFlags{ diff --git a/gen/network.go b/gen/network.go index b925a23ca..abf4868a8 100644 --- a/gen/network.go +++ b/gen/network.go @@ -332,6 +332,13 @@ type NetworkOptions struct { // Can be replaced with Erlang protocol for Erlang/OTP compatibility. Proto NetworkProto + // SoftwareKeepAliveMisses sets how many consecutive keepalives from a remote node can be missed + // before the connection is considered dead. The remote node advertises its keepalive period + // during handshake; this value controls how patient we are waiting for them. + // Timeout = RemotePeriod * Misses. Zero uses DefaultSoftwareKeepAliveMisses. + // Acceptors and routes inherit this unless overridden. + SoftwareKeepAliveMisses int + // Acceptors configures listeners for incoming connections. // Node can have multiple acceptors on different ports/interfaces. // Empty means no acceptors (same as NetworkModeHidden). @@ -391,6 +398,9 @@ type NetworkFlags struct { EnableImportantDelivery bool // EnableSimultaneousConnect enables simultaneous connect detection and resolution EnableSimultaneousConnect bool + // EnableSoftwareKeepAlive enables application-level keepalive with the given period in seconds. + // Zero disables keepalive. Max 255. + EnableSoftwareKeepAlive int } // we must be able to extend this structure by introducing new features. @@ -425,6 +435,13 @@ func (nf NetworkFlags) MarshalEDF(w io.Writer) error { if nf.EnableSimultaneousConnect == true { flags |= 128 } + if nf.EnableSoftwareKeepAlive > 0 { + period := nf.EnableSoftwareKeepAlive + if period > 255 { + period = 255 + } + flags |= uint64(period) << 8 + } binary.BigEndian.PutUint64(buf[:], flags) w.Write(buf[:]) return nil @@ -446,6 +463,7 @@ func (nf *NetworkFlags) UnmarshalEDF(buf []byte) error { nf.EnableProxyAccept = (flags & 32) > 0 nf.EnableImportantDelivery = (flags & 64) > 0 nf.EnableSimultaneousConnect = (flags & 128) > 0 + nf.EnableSoftwareKeepAlive = int((flags >> 8) & 0xFF) return nil } @@ -620,6 +638,10 @@ type AcceptorOptions struct { // rejected immediately with a "busy" reason. // Zero (default) means unlimited. MaxHandshakes int + + // SoftwareKeepAliveMisses sets how many consecutive keepalives from a remote node can be missed + // before the connection is considered dead. Zero inherits from NetworkOptions or uses default. + SoftwareKeepAliveMisses int } // Handshake defines handshake interface @@ -794,6 +816,10 @@ type NetworkRoute struct { AtomMapping map[Atom]Atom LogLevel LogLevel + + // SoftwareKeepAliveMisses sets how many consecutive keepalives from a remote node can be missed + // before the connection is considered dead. Zero inherits from NetworkOptions or uses default. + SoftwareKeepAliveMisses int } type NetworkProxyRoute struct { diff --git a/lib/flusher.go b/lib/flusher.go index 6a48339a2..a18b309d6 100644 --- a/lib/flusher.go +++ b/lib/flusher.go @@ -15,8 +15,10 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time f := &flusher{ writer: bufio.NewWriter(w), } - // first time it should be longer - f.timer = time.AfterFunc(latency*10, func() { + if closer, ok := w.(io.Closer); ok { + f.conn = closer + } + callback := func() { f.Lock() defer f.Unlock() @@ -25,6 +27,9 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time f.writer.Write(keepalive) if err := f.writer.Flush(); err != nil { f.err = err + if f.conn != nil { + f.conn.Close() + } return } @@ -34,36 +39,49 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time if err := f.writer.Flush(); err != nil { f.err = err + if f.conn != nil { + f.conn.Close() + } return } f.pending = false - f.timer.Reset(latency) - }) + f.timer.Reset(keepalivePeriod) + } + f.Lock() + f.timer = time.AfterFunc(latency*10, callback) + f.Unlock() return f - } func NewFlusher(w io.Writer) io.Writer { f := &flusher{ writer: bufio.NewWriter(w), } - f.timer = time.AfterFunc(latency, func() { + if closer, ok := w.(io.Closer); ok { + f.conn = closer + } + callback := func() { f.Lock() defer f.Unlock() if f.pending == false { - // nothing to write return } if err := f.writer.Flush(); err != nil { f.err = err + if f.conn != nil { + f.conn.Close() + } return } f.pending = false f.timer.Reset(latency) - }) + } + f.Lock() + f.timer = time.AfterFunc(latency, callback) + f.Unlock() return f } @@ -73,6 +91,7 @@ type flusher struct { writer *bufio.Writer pending bool err error + conn io.Closer } func (f *flusher) Write(b []byte) (n int, err error) { @@ -85,13 +104,11 @@ func (f *flusher) Write(b []byte) (n int, err error) { l := len(b) - // write data to the buffer for { n, e := f.writer.Write(b) if e != nil { return n, e } - // check if something left l -= n if l > 0 { continue @@ -103,12 +120,15 @@ func (f *flusher) Write(b []byte) (n int, err error) { return len(b), nil } - // if f.writer.Size() > 65000 { - // f.writer.Flush() - // return len(b), nil - // } - f.pending = true f.timer.Reset(latency) return len(b), nil } + +func (f *flusher) Stop() { + f.Lock() + defer f.Unlock() + if f.timer != nil { + f.timer.Stop() + } +} diff --git a/net/handshake/types.go b/net/handshake/types.go index 65bbec1db..131270c59 100644 --- a/net/handshake/types.go +++ b/net/handshake/types.go @@ -1,9 +1,10 @@ package handshake import ( + "sync" + "ergo.services/ergo/gen" "ergo.services/ergo/net/edf" - "sync" ) const ( @@ -70,6 +71,8 @@ type ConnectionOptions struct { DecodeAtomCache *sync.Map DecodeRegCache *sync.Map DecodeErrCache *sync.Map + + SoftwareKeepAliveMisses int } func init() { diff --git a/net/proto/connection.go b/net/proto/connection.go index a139faf95..192bc848b 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -66,6 +66,12 @@ type connection struct { reconnections uint64 + softwareKeepAlive bool + softwareKeepAliveMessage []byte + softwareKeepAlivePeriod time.Duration // how often I send + softwareKeepAliveMisses int + softwareKeepAliveTimeout time.Duration // how long I wait (peer period * misses) + order uint32 terminated bool wg sync.WaitGroup @@ -1487,9 +1493,14 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ c.pool_mutex.Unlock() return fmt.Errorf("pool size limit") } - pi := &pool_item{ - connection: conn, - fl: lib.NewFlusher(conn), + // clear handshake write deadline + conn.SetWriteDeadline(time.Time{}) + + pi := &pool_item{connection: conn} + if c.softwareKeepAlive { + pi.fl = lib.NewFlusherWithKeepAlive(conn, c.softwareKeepAliveMessage, c.softwareKeepAlivePeriod) + } else { + pi.fl = lib.NewFlusher(conn) } c.pool = append(c.pool, pi) c.pool_mutex.Unlock() @@ -1524,7 +1535,15 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ continue } pi.connection = nc - pi.fl = lib.NewFlusher(nc) + nc.SetWriteDeadline(time.Time{}) + if stopper, ok := pi.fl.(interface{ Stop() }); ok { + stopper.Stop() + } + if c.softwareKeepAlive { + pi.fl = lib.NewFlusherWithKeepAlive(nc, c.softwareKeepAliveMessage, c.softwareKeepAlivePeriod) + } else { + pi.fl = lib.NewFlusher(nc) + } tail = t atomic.AddUint64(&c.reconnections, 1) @@ -1576,21 +1595,36 @@ func (c *connection) serve(conn net.Conn, tail []byte) { buf := lib.TakeBuffer() buf.Append(tail) - // remove the deadline - conn.SetReadDeadline(time.Time{}) + // replace handshake read deadline with keepalive deadline or infinite + if c.softwareKeepAlive { + conn.SetReadDeadline(time.Now().Add(c.softwareKeepAliveTimeout)) + } else { + conn.SetReadDeadline(time.Time{}) + } for { // read packet buftail, err := c.read(conn, buf) if err != nil || buftail == nil { if err != nil { - c.log.Trace("link with %s closed: %s", conn.RemoteAddr(), err) + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + c.log.Warning("software keepalive timeout on %s", conn.RemoteAddr()) + c.Terminate(gen.ErrTimeout) + } else { + c.log.Trace("link with %s closed: %s", conn.RemoteAddr(), err) + } } lib.ReleaseBuffer(buf) conn.Close() return } + // reset deadline after successful read + if c.softwareKeepAlive { + timeout := c.softwareKeepAliveTimeout + conn.SetReadDeadline(time.Now().Add(timeout)) + } + if buf.B[0] != protoMagic { c.log.Error("recevied malformed packet from %s (incorrect proto)", conn.RemoteAddr()) lib.ReleaseBuffer(buf) @@ -1605,6 +1639,13 @@ func (c *connection) serve(conn net.Conn, tail []byte) { return } + // handle keepalive silently — don't count, don't queue + if buf.B[7] == protoMessageSoftwareKeepAlive { + lib.ReleaseBuffer(buf) + buf = buftail + continue + } + recvN++ atomic.AddUint64(&c.messagesIn, 1) diff --git a/net/proto/enp.go b/net/proto/enp.go index 8b4293ee2..93a09f3b3 100644 --- a/net/proto/enp.go +++ b/net/proto/enp.go @@ -68,6 +68,24 @@ func (e *enp) NewConnection(core gen.Core, result gen.HandshakeResult, log gen.L Cache: new(sync.Map), }, requests: make(map[gen.Ref]chan MessageResult), + + softwareKeepAlive: result.NodeFlags.EnableSoftwareKeepAlive > 0 && + result.PeerFlags.EnableSoftwareKeepAlive > 0, + } + + if conn.softwareKeepAlive { + myPeriod := time.Duration(result.NodeFlags.EnableSoftwareKeepAlive) * time.Second + peerPeriod := time.Duration(result.PeerFlags.EnableSoftwareKeepAlive) * time.Second + misses := opts.SoftwareKeepAliveMisses + if misses == 0 { + misses = gen.DefaultSoftwareKeepAliveMisses + } + conn.softwareKeepAlivePeriod = myPeriod + conn.softwareKeepAliveMisses = misses + conn.softwareKeepAliveTimeout = peerPeriod * time.Duration(misses) + conn.softwareKeepAliveMessage = []byte{ + protoMagic, protoVersion, 0, 0, 0, 8, 0, protoMessageSoftwareKeepAlive, + } } if len(result.AtomMapping) > 0 { diff --git a/net/proto/types.go b/net/proto/types.go index 796b98c77..1cdca902c 100644 --- a/net/proto/types.go +++ b/net/proto/types.go @@ -46,6 +46,9 @@ const ( protoMessageF byte = 202 // fragmented protoMessageP byte = 203 // proxy + // software keepalive + protoMessageSoftwareKeepAlive byte = 208 + // TODO // protoFragmentSize int = 65000 ) diff --git a/node/acceptor.go b/node/acceptor.go index 63002ecd5..d212ee7ec 100644 --- a/node/acceptor.go +++ b/node/acceptor.go @@ -29,6 +29,8 @@ type acceptor struct { handshaking atomic.Int32 // current number of in-flight handshakes maxHandshakes int32 // 0 = unlimited handshakeErrors atomic.Uint64 // cumulative handshake failures + + software_keepalive_misses int } // gen.Acceptor interface implementation diff --git a/node/network.go b/node/network.go index aaf1b04bb..f81ba3dbe 100644 --- a/node/network.go +++ b/node/network.go @@ -52,8 +52,9 @@ type network struct { handshakes sync.Map // .Version().String() -> handshake protos sync.Map // .Version().String() -> proto - cookie string - maxmessagesize int + cookie string + maxmessagesize int + softwareKeepAliveMisses int staticRoutes *staticRoutes staticProxies *staticProxies @@ -815,6 +816,7 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection if err != nil { return nil, err } + conn.SetDeadline(time.Now().Add(gen.DefaultHandshakeTimeout)) hopts := gen.HandshakeOptions{ Cookie: route.Cookie, @@ -832,6 +834,7 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection if hopts.Flags.Enable == false { hopts.Flags = n.flags } + // period for keepalive is already in hopts.Flags (from route.Flags or n.flags) result, err := hs.Start(n.node, conn, hopts) if err != nil { @@ -868,6 +871,12 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection } log.setSource(logSource) + // inject software keepalive misses into ConnectionOptions + if opts, ok := result.Custom.(handshake.ConnectionOptions); ok { + opts.SoftwareKeepAliveMisses = n.keepAliveMisses(route.SoftwareKeepAliveMisses) + result.Custom = opts + } + pconn, err := proto.NewConnection(n.node, result, log) if err != nil { conn.Close() @@ -879,8 +888,10 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection if err != nil { return nil, nil, err } + c.SetDeadline(time.Now().Add(gen.DefaultHandshakeTimeout)) tail, err := hs.Join(n.node, c, id, hopts) if err != nil { + c.Close() return nil, nil, err } return c, tail, nil @@ -958,6 +969,16 @@ func (n *network) connectProxy(name gen.Atom, route gen.NetworkProxyRoute) (gen. return nil, gen.ErrUnsupported } +func (n *network) keepAliveMisses(v int) int { + if v > 0 { + return v + } + if n.softwareKeepAliveMisses > 0 { + return n.softwareKeepAliveMisses + } + return gen.DefaultSoftwareKeepAliveMisses +} + func (n *network) stop() error { if swapped := n.running.CompareAndSwap(true, false); swapped == false { return fmt.Errorf("network stack is already stopped") @@ -1013,6 +1034,7 @@ func (n *network) start(options gen.NetworkOptions) error { options.Flags = gen.DefaultNetworkFlags } n.flags = options.Flags + n.softwareKeepAliveMisses = options.SoftwareKeepAliveMisses if options.Mode == gen.NetworkModeHidden { static, err := n.registrar.Register(n.node, gen.RegisterRoutes{}) @@ -1231,6 +1253,8 @@ func (n *network) startAcceptor(a gen.AcceptorOptions) (*acceptor, error) { route_host: a.RouteHost, route_port: a.RoutePort, maxHandshakes: int32(a.MaxHandshakes), + + software_keepalive_misses: n.keepAliveMisses(a.SoftwareKeepAliveMisses), } if a.Cookie == "" { acceptor.cookie = n.cookie @@ -1314,6 +1338,7 @@ func (n *network) accept(a *acceptor) { return exists }, } + // period for keepalive is already in hopts.Flags (from a.flags) for { c, err := a.l.Accept() if err != nil { @@ -1347,6 +1372,7 @@ func (n *network) accept(a *acceptor) { } func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOptions) { + c.SetDeadline(time.Now().Add(gen.DefaultHandshakeTimeout)) result, err := a.handshake.Accept(n.node, c, hopts) if err != nil { if err != io.EOF { @@ -1390,6 +1416,19 @@ func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOpt return } + // Join handshake for a connection that no longer exists — peer's pool expansion + // arrived after the connection was terminated. Nothing to join, close silently. + if result.PeerCreation == 0 { + c.Close() + return + } + + // inject software keepalive misses from acceptor into ConnectionOptions + if opts, ok := result.Custom.(handshake.ConnectionOptions); ok { + opts.SoftwareKeepAliveMisses = a.software_keepalive_misses + result.Custom = opts + } + log := createLog(n.node.Log().Level(), n.node.dolog) logSource := gen.MessageLogNetwork{ Node: n.node.name, From b9ff6601a426866e50f56ce751a16b5a8ae45bce Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 10 Mar 2026 13:28:29 +0100 Subject: [PATCH 044/122] add fragmentation feature --- docs/networking/network-stack.md | 38 +- gen/default.go | 5 +- gen/network.go | 28 +- net/handshake/types.go | 3 + net/proto/connection.go | 427 +++++++++++++++++- net/proto/enp.go | 31 +- node/network.go | 16 +- .../t010_fragmentation_test.go | 297 ++++++++++++ .../t011_fragmentation_load_test.go | 323 +++++++++++++ 9 files changed, 1135 insertions(+), 33 deletions(-) create mode 100644 testing/tests/002_distributed/t010_fragmentation_test.go create mode 100644 testing/tests/002_distributed/t011_fragmentation_load_test.go diff --git a/docs/networking/network-stack.md b/docs/networking/network-stack.md index e3c3a8820..9213a259d 100644 --- a/docs/networking/network-stack.md +++ b/docs/networking/network-stack.md @@ -157,6 +157,39 @@ The order byte preserves message ordering per sender. Messages from the same sen For details on protocol framing, order bytes, receive queue distribution, and the exact byte layout, see [Network Transparency](network-transparency.md). +### Message Fragmentation + +*Introduced in v3.3.0.* + +When a message exceeds the fragment size threshold (default 65000 bytes), the framework splits it into smaller pieces for transmission and reassembles them on the receiving side. This happens after compression -- if a compressed message is still too large, it gets fragmented. From your code's perspective, nothing changes. You send a large message, and it arrives intact. + +Fragmentation works with all message types: regular sends, important delivery, calls, and events. It composes with compression -- a message can be compressed first, then fragmented, and on the receiving side defragmented and then decompressed. + +When [`KeepNetworkOrder`](network-transparency.md#message-ordering) is disabled for a process, the framework distributes fragments across all TCP connections in the pool, using the full bandwidth of the connection. This is useful for transferring large payloads where throughput matters more than ordering. When `KeepNetworkOrder` is enabled (the default), all fragments travel through a single TCP connection to preserve message ordering for that sender. + +Both nodes must have `EnableFragmentation` in their network flags. If either side doesn't support it, large messages are sent as-is (subject to `MaxMessageSize` limits). During handshake, nodes exchange their fragmentation capability, and the feature activates only when both sides agree. + +`MaxMessageSize` is a logical limit on the EDF-encoded message, checked before compression and fragmentation. On the receiving side, the framework tracks the accumulated size of received fragments and rejects the assembly if it exceeds the limit. + +```go +node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ + Network: gen.NetworkOptions{ + Flags: gen.NetworkFlags{ + EnableFragmentation: true, // default: true + }, + FragmentSize: 65000, // bytes per fragment, 0 = default + FragmentTimeout: 30, // seconds, assembly timeout, 0 = default + MaxFragmentAssemblies: 1000, // max concurrent assemblies, 0 = default + }, +}) +``` + +`FragmentSize` controls at what point messages get split. This is a sender-side setting -- the receiver reassembles whatever arrives regardless of the sender's fragment size. Two nodes can use different fragment sizes. + +`FragmentTimeout` sets how long the receiver waits for all fragments before discarding an incomplete assembly. If a sender crashes mid-message or a connection drops, partial assemblies are cleaned up after this timeout. + +`MaxFragmentAssemblies` limits how many messages can be simultaneously reassembled per connection, protecting against memory exhaustion from many concurrent large messages. + ## Network Transparency in Practice Network transparency means remote operations look like local operations. You send to a PID without checking if it's local or remote. You establish links and monitors the same way regardless of location. The framework handles discovery, encoding, and transmission automatically. @@ -186,9 +219,12 @@ node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ EnableRemoteSpawn: true, EnableRemoteApplicationStart: true, EnableImportantDelivery: true, + EnableFragmentation: true, // default: true EnableSoftwareKeepAlive: 15, // seconds, 0 to disable }, SoftwareKeepAliveMisses: 3, // tolerate 3 missed keepalives + FragmentSize: 65000, // 0 = default + FragmentTimeout: 30, // seconds, 0 = default Acceptors: []gen.AcceptorOptions{ { Port: 15000, @@ -206,7 +242,7 @@ node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ **MaxMessageSize** - Maximum incoming message size. Protects against memory exhaustion. Default unlimited (fine for trusted clusters). -**Flags** - Control capabilities. Remote nodes learn your flags during handshake and can only use features you've enabled. `EnableRemoteSpawn` allows spawning (with explicit permission per process). `EnableImportantDelivery` enables delivery confirmation. `EnableSoftwareKeepAlive` sets the keepalive period in seconds (see [Software Keepalive](#software-keepalive)). +**Flags** - Control capabilities. Remote nodes learn your flags during handshake and can only use features you've enabled. `EnableRemoteSpawn` allows spawning (with explicit permission per process). `EnableImportantDelivery` enables delivery confirmation. `EnableFragmentation` enables message fragmentation for large messages (both sides must enable). `EnableSoftwareKeepAlive` sets the keepalive period in seconds (see [Software Keepalive](#software-keepalive)). **Acceptors** - Define listeners for incoming connections. Multiple acceptors on different ports are supported. Each can have its own cookie, TLS, and protocol. diff --git a/gen/default.go b/gen/default.go index 7809ca0c7..a916db56d 100644 --- a/gen/default.go +++ b/gen/default.go @@ -27,12 +27,15 @@ var ( DefaultHandshakeTimeout time.Duration = 5 * time.Second DefaultSoftwareKeepAliveMisses int = 3 + DefaultFragmentSize int = 65000 + DefaultFragmentTimeout time.Duration = 30 * time.Second + DefaultMaxFragmentAssemblies int = 1000 DefaultNetworkFlags = NetworkFlags{ Enable: true, EnableRemoteSpawn: true, EnableRemoteApplicationStart: true, - EnableFragmentation: false, + EnableFragmentation: true, EnableProxyTransit: false, EnableProxyAccept: true, EnableImportantDelivery: true, diff --git a/gen/network.go b/gen/network.go index abf4868a8..236673fd6 100644 --- a/gen/network.go +++ b/gen/network.go @@ -361,9 +361,20 @@ type NetworkOptions struct { // Controls how proxy connections are routed through this node. ProxyTransit ProxyTransitOptions - // TODO - // FragmentationUnit chunck size in bytes - //FragmentationUnit int + // FragmentSize sets the maximum fragment packet size in bytes. + // Messages larger than this are split into fragments for transmission. + // Zero uses DefaultFragmentSize (65000). Sender-local, no negotiation needed. + FragmentSize int + + // FragmentTimeout sets the maximum time in seconds to wait for all fragments of a message. + // Incomplete assemblies are cleaned up after this duration. + // Zero uses DefaultFragmentTimeout (30s). + FragmentTimeout int + + // MaxFragmentAssemblies limits concurrent unordered fragment assemblies per connection. + // Protects against memory exhaustion from many simultaneous large messages. + // Zero uses DefaultMaxFragmentAssemblies (1000). + MaxFragmentAssemblies int } type ProxyAcceptOptions struct { @@ -551,6 +562,17 @@ type RemoteNodeInfo struct { // Reconnections is the total number of pool item reconnections. // A non-zero value indicates connection instability. Reconnections uint64 + + // FragmentsSent is the total number of individual fragments sent. + FragmentsSent uint64 + // FragmentMessagesSent is the total number of messages that were fragmented for sending. + FragmentMessagesSent uint64 + // FragmentsReceived is the total number of individual fragments received. + FragmentsReceived uint64 + // FragmentMessagesRecv is the total number of fragmented messages successfully reassembled. + FragmentMessagesRecv uint64 + // FragmentTimeouts is the total number of fragment assemblies that timed out. + FragmentTimeouts uint64 } // AcceptorOptions configures a network listener (acceptor) for incoming connections. diff --git a/net/handshake/types.go b/net/handshake/types.go index 131270c59..10a647ebb 100644 --- a/net/handshake/types.go +++ b/net/handshake/types.go @@ -73,6 +73,9 @@ type ConnectionOptions struct { DecodeErrCache *sync.Map SoftwareKeepAliveMisses int + FragmentSize int + FragmentTimeout int + MaxFragmentAssemblies int } func init() { diff --git a/net/proto/connection.go b/net/proto/connection.go index 192bc848b..049019e39 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -72,11 +72,41 @@ type connection struct { softwareKeepAliveMisses int softwareKeepAliveTimeout time.Duration // how long I wait (peer period * misses) + // fragmentation + fragmentation bool + fragmentSize int + fragmentTimeout time.Duration + maxFragmentAssemblies int + nextSequenceID atomic.Uint32 + + // ordered fragment assembly (per recv queue, no mutex) + orderedFragments []map[uint32]*fragmentAssembly + + // unordered fragment assembly (order = 0 only) + sharedFragMu sync.Mutex + sharedFragments map[uint32]*fragmentAssembly + sharedFragTimer *time.Timer + + // fragment statistics + fragmentsSent atomic.Uint64 + fragmentMessagesSent atomic.Uint64 + fragmentsReceived atomic.Uint64 + fragmentMessagesRecv atomic.Uint64 + fragmentTimeouts atomic.Uint64 + order uint32 terminated bool wg sync.WaitGroup } +type fragmentAssembly struct { + totalFragments uint16 + received uint16 + totalBytes int + payloads [][]byte + deadline time.Time +} + type pool_item struct { connection net.Conn fl io.Writer @@ -130,6 +160,12 @@ func (c *connection) Info() gen.RemoteNodeInfo { TransitBytesOut: atomic.LoadUint64(&c.transitOut), Reconnections: atomic.LoadUint64(&c.reconnections), + + FragmentsSent: c.fragmentsSent.Load(), + FragmentMessagesSent: c.fragmentMessagesSent.Load(), + FragmentsReceived: c.fragmentsReceived.Load(), + FragmentMessagesRecv: c.fragmentMessagesRecv.Load(), + FragmentTimeouts: c.fragmentTimeouts.Load(), } return info } @@ -1585,6 +1621,11 @@ func (c *connection) Terminate(reason error) { for _, pi := range c.pool { pi.connection.Close() } + + // cleanup fragment state + if c.sharedFragTimer != nil { + c.sharedFragTimer.Stop() + } } func (c *connection) serve(conn net.Conn, tail []byte) { @@ -1666,14 +1707,14 @@ func (c *connection) serve(conn net.Conn, tail []byte) { queue.Push(buf) if queue.Lock() { - go c.handleRecvQueue(queue) + go c.handleRecvQueue(queue, qN) } buf = buftail } } -func (c *connection) handleRecvQueue(q lib.QueueMPSC) { +func (c *connection) handleRecvQueue(q lib.QueueMPSC, qIdx int) { if lib.Recover() { defer func() { if r := recover(); r != nil { @@ -1688,10 +1729,26 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { if lib.Trace() { c.log.Trace("start handling the message queue") } + + // per-queue ordered fragment assembly (persists across goroutine re-entries) + var localFragments map[uint32]*fragmentAssembly + if c.fragmentation && qIdx < len(c.orderedFragments) { + localFragments = c.orderedFragments[qIdx] + } for { v, ok := q.Pop() if ok == false { - // no more items in the queue, unlock it + // queue drained -- clean stale ordered assemblies (safe: we hold queue lock) + if localFragments != nil && len(localFragments) > 0 { + now := time.Now() + for seqID, asm := range localFragments { + if now.After(asm.deadline) { + delete(localFragments, seqID) + c.fragmentTimeouts.Add(1) + } + } + } + q.Unlock() // but check the queue before the exit this goroutine @@ -1727,6 +1784,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { idFrom := binary.BigEndian.Uint64(buf.B[8:16]) priority := gen.MessagePriority(buf.B[16] & 3) important := (buf.B[16] & 128) > 0 + refID := binary.BigEndian.Uint64(buf.B[17:25]) idTO := binary.BigEndian.Uint64(buf.B[25:33]) msg, tail, err := edf.Decode(buf.B[33:], c.decodeOptions) @@ -1766,7 +1824,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { continue } - opts.Ref.ID[0] = binary.BigEndian.Uint64(buf.B[17:25]) + opts.Ref.ID[0] = refID c.SendResponseError(to, from, opts, err) case protoMessageName, protoMessageNameCache: // name, chached name @@ -1814,6 +1872,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { idFrom := binary.BigEndian.Uint64(buf.B[8:16]) priority := gen.MessagePriority(buf.B[16] & 3) important := (buf.B[16] & 128) > 0 + refID := binary.BigEndian.Uint64(buf.B[17:25]) msg, tail, err := edf.Decode(data, c.decodeOptions) if releaseBuffer { @@ -1857,7 +1916,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { continue } - opts.Ref.ID[0] = binary.BigEndian.Uint64(buf.B[17:25]) + opts.Ref.ID[0] = refID c.SendResponseError(gen.PID{}, from, opts, err) case protoMessageAlias: @@ -1869,6 +1928,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { idFrom := binary.BigEndian.Uint64(buf.B[8:16]) priority := gen.MessagePriority(buf.B[16] & 3) important := (buf.B[16] & 128) > 0 + refID := binary.BigEndian.Uint64(buf.B[17:25]) idTo := [3]uint64{ binary.BigEndian.Uint64(buf.B[25:33]), binary.BigEndian.Uint64(buf.B[33:41]), @@ -1912,7 +1972,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { continue } - opts.Ref.ID[0] = binary.BigEndian.Uint64(buf.B[17:25]) + opts.Ref.ID[0] = refID c.SendResponseError(gen.PID{}, from, opts, err) case protoRequestPID: @@ -2654,9 +2714,28 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { continue } - // case protoMessageF: - // TODO fragmentation - // TODO check the message size after assembling + case protoMessageF: + if c.fragmentation == false { + c.log.Warning("received fragment but fragmentation disabled, ignored") + continue + } + + order := buf.B[6] + if order > 0 && localFragments != nil { + // ordered path: per-queue assembly + buf = c.handleFragmentOrdered(buf, localFragments) + if buf == nil { + continue + } + goto re + } + + // unordered path: shared assembly + buf = c.handleFragmentUnordered(buf) + if buf == nil { + continue + } + goto re // case protoMessageP: // TODO proxy @@ -2666,12 +2745,6 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC) { lib.ReleaseBuffer(buf) } - // TODO - // check if connection has been terminated - // if c.terminated { - // return - // } - } } @@ -3015,6 +3088,10 @@ func (c *connection) wait() { func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compression) error { + if c.peer_maxmessagesize > 0 && buf.Len() > c.peer_maxmessagesize { + return gen.ErrTooLarge + } + if compression.Enable && buf.Len() > compression.Threshold { var zbuf *lib.Buffer var err error @@ -3057,8 +3134,9 @@ func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compress buf = zbuf } - if c.peer_maxmessagesize > 0 && buf.Len() > c.peer_maxmessagesize { - return gen.ErrTooLarge + // fragmentation + if c.fragmentation == true && buf.Len() > c.fragmentSize { + return c.sendFragmented(buf, order) } var pi *pool_item @@ -3078,11 +3156,6 @@ func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compress } c.pool_mutex.RUnlock() - // TODO - // add proxy, fragmentation support - // c.transitOut++ - // if buf.Len() < protoFragmentSize { - bufLen := uint64(buf.Len()) _, err := pi.fl.Write(buf.B) lib.ReleaseBuffer(buf) @@ -3094,11 +3167,315 @@ func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compress atomic.AddUint64(&c.messagesOut, 1) atomic.AddUint64(&c.bytesOut, bufLen) return nil +} + +func (c *connection) sendFragmented(buf *lib.Buffer, order uint8) error { + data := buf.B // entire original message including ENP header + maxPayload := c.fragmentSize - 16 // 16 = ENP header (8) + fragment header (8) - // } + totalFragments := uint16((len(data) + maxPayload - 1) / maxPayload) + + sequenceID := c.nextSequenceID.Add(1) + + if lib.Trace() { + c.log.Trace("fragmenting message: %d bytes, %d fragments (seq=%d)", + len(data), totalFragments, sequenceID) + } + + // for ordered messages, select pool item once (all fragments must go + // through the same TCP connection to preserve order on the receiver) + var orderedPI *pool_item + if order > 0 { + c.pool_mutex.RLock() + l := len(c.pool) + if l == 0 { + c.pool_mutex.RUnlock() + lib.ReleaseBuffer(buf) + return gen.ErrNoConnection + } + orderedPI = c.pool[int(order)%l] + c.pool_mutex.RUnlock() + } + + offset := 0 + for idx := uint16(0); idx < totalFragments; idx++ { + chunkSize := len(data) - offset + if chunkSize > maxPayload { + chunkSize = maxPayload + } + + frag := lib.TakeBuffer() + frag.Allocate(16 + chunkSize) + + // standard ENP header + frag.B[0] = protoMagic + frag.B[1] = protoVersion + binary.BigEndian.PutUint32(frag.B[2:6], uint32(len(frag.B))) + frag.B[6] = order + frag.B[7] = protoMessageF + + // fragment header + binary.BigEndian.PutUint32(frag.B[8:12], sequenceID) + binary.BigEndian.PutUint16(frag.B[12:14], idx) + binary.BigEndian.PutUint16(frag.B[14:16], totalFragments) + + // payload: chunk of original message + copy(frag.B[16:], data[offset:offset+chunkSize]) + offset += chunkSize + + // select pool item + pi := orderedPI + if order == 0 { + c.pool_mutex.RLock() + l := len(c.pool) + if l == 0 { + c.pool_mutex.RUnlock() + lib.ReleaseBuffer(frag) + lib.ReleaseBuffer(buf) + return gen.ErrNoConnection + } + neworder := atomic.AddUint32(&c.order, 1) + pi = c.pool[int(neworder)%l] + c.pool_mutex.RUnlock() + } + + fragLen := uint64(frag.Len()) + _, err := pi.fl.Write(frag.B) + lib.ReleaseBuffer(frag) + if err != nil { + pi.connection.Close() + lib.ReleaseBuffer(buf) + return err + } + + atomic.AddUint64(&c.messagesOut, 1) + atomic.AddUint64(&c.bytesOut, fragLen) + } + + lib.ReleaseBuffer(buf) + + c.fragmentsSent.Add(uint64(totalFragments)) + c.fragmentMessagesSent.Add(1) + + return nil +} + +const maxFragmentCount = 10000 + +func (c *connection) handleFragmentOrdered(buf *lib.Buffer, assemblies map[uint32]*fragmentAssembly) *lib.Buffer { + if buf.Len() < 16 { + c.log.Warning("fragment too short: %d bytes", buf.Len()) + return nil + } + + sequenceID := binary.BigEndian.Uint32(buf.B[8:12]) + fragIndex := binary.BigEndian.Uint16(buf.B[12:14]) + totalFragments := binary.BigEndian.Uint16(buf.B[14:16]) + payload := buf.B[16:] + + if fragIndex >= totalFragments || totalFragments == 0 { + c.log.Warning("invalid fragment index %d/%d (seq=%d)", fragIndex, totalFragments, sequenceID) + return nil + } + + asm, exists := assemblies[sequenceID] + if exists == false { + if totalFragments > maxFragmentCount { + c.log.Warning("too many fragments: %d (seq=%d)", totalFragments, sequenceID) + return nil + } + asm = &fragmentAssembly{ + totalFragments: totalFragments, + payloads: make([][]byte, 0, totalFragments), + deadline: time.Now().Add(c.fragmentTimeout), + } + assemblies[sequenceID] = asm + } - // message must be fragmented - // panic("TODO") + // rejected assembly (exceeded maxmessagesize), ignore subsequent fragments + if asm.payloads == nil { + return nil + } + + if asm.totalFragments != totalFragments { + c.log.Warning("fragment total mismatch (seq=%d)", sequenceID) + delete(assemblies, sequenceID) + return nil + } + + // TCP order guarantee -- append + asm.payloads = append(asm.payloads, append([]byte(nil), payload...)) + asm.received++ + asm.totalBytes += len(payload) + + // check accumulated size against receiver limit + if c.node_maxmessagesize > 0 && asm.totalBytes > c.node_maxmessagesize { + asm.payloads = nil + c.log.Warning("fragmented message exceeds max size: %d (max %d, seq=%d)", + asm.totalBytes, c.node_maxmessagesize, sequenceID) + return nil + } + + c.fragmentsReceived.Add(1) + + if asm.received < asm.totalFragments { + return nil + } + + // assembly complete + delete(assemblies, sequenceID) + + // cleanup stale assemblies from dead senders + if len(assemblies) > 0 { + now := time.Now() + for seqID, asm := range assemblies { + if now.After(asm.deadline) { + delete(assemblies, seqID) + c.fragmentTimeouts.Add(1) + } + } + } + + reassembled := lib.TakeBuffer() + reassembled.Allocate(asm.totalBytes) + + offset := 0 + for _, p := range asm.payloads { + copy(reassembled.B[offset:], p) + offset += len(p) + } + + c.fragmentMessagesRecv.Add(1) + + if lib.Trace() { + c.log.Trace("fragment assembly complete: seq=%d, %d bytes, %d fragments", + sequenceID, asm.totalBytes, asm.totalFragments) + } + + return reassembled +} + +func (c *connection) handleFragmentUnordered(buf *lib.Buffer) *lib.Buffer { + if buf.Len() < 16 { + c.log.Warning("fragment too short: %d bytes", buf.Len()) + return nil + } + + sequenceID := binary.BigEndian.Uint32(buf.B[8:12]) + fragIndex := binary.BigEndian.Uint16(buf.B[12:14]) + totalFragments := binary.BigEndian.Uint16(buf.B[14:16]) + payload := buf.B[16:] + + if fragIndex >= totalFragments || totalFragments == 0 { + c.log.Warning("invalid fragment index %d/%d (seq=%d)", fragIndex, totalFragments, sequenceID) + return nil + } + + c.sharedFragMu.Lock() + + asm, exists := c.sharedFragments[sequenceID] + if exists == false { + if totalFragments > maxFragmentCount { + c.sharedFragMu.Unlock() + c.log.Warning("too many fragments: %d (seq=%d)", totalFragments, sequenceID) + return nil + } + if len(c.sharedFragments) >= c.maxFragmentAssemblies { + c.sharedFragMu.Unlock() + c.log.Warning("too many concurrent unordered assemblies, dropping fragment") + return nil + } + + asm = &fragmentAssembly{ + totalFragments: totalFragments, + payloads: make([][]byte, totalFragments), // indexed + deadline: time.Now().Add(c.fragmentTimeout), + } + c.sharedFragments[sequenceID] = asm + c.sharedFragTimer.Reset(5 * time.Second) + } + + // rejected assembly (exceeded maxmessagesize), ignore subsequent fragments + if asm.payloads == nil { + c.sharedFragMu.Unlock() + return nil + } + + if asm.totalFragments != totalFragments { + c.sharedFragMu.Unlock() + c.log.Warning("fragment total mismatch (seq=%d)", sequenceID) + return nil + } + + // duplicate check + if asm.payloads[fragIndex] != nil { + c.sharedFragMu.Unlock() + return nil + } + + asm.payloads[fragIndex] = append([]byte(nil), payload...) + asm.received++ + asm.totalBytes += len(payload) + + // check accumulated size against receiver limit + if c.node_maxmessagesize > 0 && asm.totalBytes > c.node_maxmessagesize { + asm.payloads = nil + c.sharedFragMu.Unlock() + c.log.Warning("fragmented message exceeds max size: %d (max %d, seq=%d)", + asm.totalBytes, c.node_maxmessagesize, sequenceID) + return nil + } + + c.fragmentsReceived.Add(1) + + if asm.received < asm.totalFragments { + c.sharedFragMu.Unlock() + return nil + } + + // assembly complete + delete(c.sharedFragments, sequenceID) + c.sharedFragMu.Unlock() + + // build reassembled message outside mutex + reassembled := lib.TakeBuffer() + reassembled.Allocate(asm.totalBytes) + + offset := 0 + for _, p := range asm.payloads { + copy(reassembled.B[offset:], p) + offset += len(p) + } + + c.fragmentMessagesRecv.Add(1) + + if lib.Trace() { + c.log.Trace("fragment assembly complete: seq=%d, %d bytes, %d fragments", + sequenceID, asm.totalBytes, asm.totalFragments) + } + + return reassembled +} + +func (c *connection) cleanupSharedFragments() { + c.sharedFragMu.Lock() + defer c.sharedFragMu.Unlock() + + now := time.Now() + for seqID, asm := range c.sharedFragments { + if now.After(asm.deadline) { + if lib.Trace() { + c.log.Trace("unordered fragment timeout: seq=%d, %d/%d received", + seqID, asm.received, asm.totalFragments) + } + delete(c.sharedFragments, seqID) + c.fragmentTimeouts.Add(1) + } + } + + if len(c.sharedFragments) > 0 { + c.sharedFragTimer.Reset(5 * time.Second) + } } func (c *connection) waitResult(ref gen.Ref, ch chan MessageResult) (result MessageResult) { diff --git a/net/proto/enp.go b/net/proto/enp.go index 93a09f3b3..e34fd394c 100644 --- a/net/proto/enp.go +++ b/net/proto/enp.go @@ -88,6 +88,26 @@ func (e *enp) NewConnection(core gen.Core, result gen.HandshakeResult, log gen.L } } + if result.NodeFlags.EnableFragmentation == true && + result.PeerFlags.EnableFragmentation == true { + conn.fragmentation = true + conn.fragmentSize = gen.DefaultFragmentSize + if opts.FragmentSize > 0 { + conn.fragmentSize = opts.FragmentSize + } + conn.fragmentTimeout = gen.DefaultFragmentTimeout + if opts.FragmentTimeout > 0 { + conn.fragmentTimeout = time.Duration(opts.FragmentTimeout) * time.Second + } + conn.maxFragmentAssemblies = gen.DefaultMaxFragmentAssemblies + if opts.MaxFragmentAssemblies > 0 { + conn.maxFragmentAssemblies = opts.MaxFragmentAssemblies + } + conn.sharedFragments = make(map[uint32]*fragmentAssembly) + conn.sharedFragTimer = time.AfterFunc(time.Hour, conn.cleanupSharedFragments) + conn.sharedFragTimer.Stop() + } + if len(result.AtomMapping) > 0 { conn.encodeOptions.AtomMapping = &sync.Map{} conn.decodeOptions.AtomMapping = &sync.Map{} @@ -99,10 +119,19 @@ func (e *enp) NewConnection(core gen.Core, result gen.HandshakeResult, log gen.L // init recv queues. create 4 recv queues per connection // since the decoding is more costly comparing to the encoding - for i := 0; i < opts.PoolSize*4; i++ { + numQueues := opts.PoolSize * 4 + for i := 0; i < numQueues; i++ { conn.recvQueues = append(conn.recvQueues, lib.NewQueueMPSC()) } + // init per-queue ordered fragment assembly maps + if conn.fragmentation { + conn.orderedFragments = make([]map[uint32]*fragmentAssembly, numQueues) + for i := 0; i < numQueues; i++ { + conn.orderedFragments[i] = make(map[uint32]*fragmentAssembly) + } + } + return conn, nil } diff --git a/node/network.go b/node/network.go index f81ba3dbe..b444fc677 100644 --- a/node/network.go +++ b/node/network.go @@ -55,6 +55,9 @@ type network struct { cookie string maxmessagesize int softwareKeepAliveMisses int + fragmentSize int + fragmentTimeout int + maxFragmentAssemblies int staticRoutes *staticRoutes staticProxies *staticProxies @@ -871,9 +874,12 @@ func (n *network) connect(name gen.Atom, route gen.NetworkRoute) (gen.Connection } log.setSource(logSource) - // inject software keepalive misses into ConnectionOptions + // inject options into ConnectionOptions if opts, ok := result.Custom.(handshake.ConnectionOptions); ok { opts.SoftwareKeepAliveMisses = n.keepAliveMisses(route.SoftwareKeepAliveMisses) + opts.FragmentSize = n.fragmentSize + opts.FragmentTimeout = n.fragmentTimeout + opts.MaxFragmentAssemblies = n.maxFragmentAssemblies result.Custom = opts } @@ -1035,6 +1041,9 @@ func (n *network) start(options gen.NetworkOptions) error { } n.flags = options.Flags n.softwareKeepAliveMisses = options.SoftwareKeepAliveMisses + n.fragmentSize = options.FragmentSize + n.fragmentTimeout = options.FragmentTimeout + n.maxFragmentAssemblies = options.MaxFragmentAssemblies if options.Mode == gen.NetworkModeHidden { static, err := n.registrar.Register(n.node, gen.RegisterRoutes{}) @@ -1423,9 +1432,12 @@ func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOpt return } - // inject software keepalive misses from acceptor into ConnectionOptions + // inject options from acceptor into ConnectionOptions if opts, ok := result.Custom.(handshake.ConnectionOptions); ok { opts.SoftwareKeepAliveMisses = a.software_keepalive_misses + opts.FragmentSize = n.fragmentSize + opts.FragmentTimeout = n.fragmentTimeout + opts.MaxFragmentAssemblies = n.maxFragmentAssemblies result.Custom = opts } diff --git a/testing/tests/002_distributed/t010_fragmentation_test.go b/testing/tests/002_distributed/t010_fragmentation_test.go new file mode 100644 index 000000000..e6c385233 --- /dev/null +++ b/testing/tests/002_distributed/t010_fragmentation_test.go @@ -0,0 +1,297 @@ +package distributed + +import ( + "fmt" + "reflect" + "testing" + "time" + + "ergo.services/ergo" + "ergo.services/ergo/act" + "ergo.services/ergo/gen" + "ergo.services/ergo/lib" +) + +var ( + t10pongCh chan any +) + +func factory_t10pong() gen.ProcessBehavior { + return &t10pong{} +} + +type t10pong struct { + act.Actor +} + +func (t *t10pong) HandleMessage(from gen.PID, message any) error { + select { + case t10pongCh <- message: + default: + } + return nil +} + +func factory_t10() gen.ProcessBehavior { + return &t10{} +} + +type t10 struct { + act.Actor + + remote gen.Atom + testcase *testcase +} + +func (t *t10) Init(args ...any) error { + t.remote = args[0].(gen.Atom) + return nil +} + +func (t *t10) HandleMessage(from gen.PID, message any) error { + if t.testcase == nil { + t.testcase = message.(*testcase) + message = initcase{} + } + + method := reflect.ValueOf(t).MethodByName(t.testcase.name) + if method.IsValid() == false { + t.testcase.err <- fmt.Errorf("unknown method %q", t.testcase.name) + t.testcase = nil + return nil + } + method.Call([]reflect.Value{reflect.ValueOf(message)}) + return nil +} + +// TestFragmentSendOrdered sends a large message with KeepNetworkOrder (order > 0). +// All fragments go to the same pool item -> same TCP -> same recv queue. +func (t *t10) TestFragmentSendOrdered(input any) { + defer func() { t.testcase = nil }() + + pid, err := t.RemoteSpawn(t.remote, "t10pong", gen.ProcessOptions{}) + if err != nil { + t.testcase.err <- err + return + } + + t10pongCh = make(chan any, 1) + + // 5000 bytes string, FragmentSize=1000 -> ~5 fragments + pingvalue := lib.RandomString(5000) + + if err := t.Send(pid, pingvalue); err != nil { + t.testcase.err <- err + return + } + + select { + case pong := <-t10pongCh: + if reflect.DeepEqual(pingvalue, pong) == false { + t.testcase.err <- fmt.Errorf("pong value mismatch (ordered)") + return + } + case <-time.NewTimer(5 * time.Second).C: + t.testcase.err <- gen.ErrTimeout + return + } + + t.testcase.err <- nil +} + +// TestFragmentSendUnordered sends a large message without KeepNetworkOrder (order = 0). +// Fragments round-robin across pool items -> different recv queues. +func (t *t10) TestFragmentSendUnordered(input any) { + defer func() { t.testcase = nil }() + + pid, err := t.RemoteSpawn(t.remote, "t10pong", gen.ProcessOptions{}) + if err != nil { + t.testcase.err <- err + return + } + + t10pongCh = make(chan any, 1) + + pingvalue := lib.RandomString(5000) + + t.SetKeepNetworkOrder(false) + defer t.SetKeepNetworkOrder(true) + + if err := t.Send(pid, pingvalue); err != nil { + t.testcase.err <- err + return + } + + select { + case pong := <-t10pongCh: + if reflect.DeepEqual(pingvalue, pong) == false { + t.testcase.err <- fmt.Errorf("pong value mismatch (unordered)") + return + } + case <-time.NewTimer(5 * time.Second).C: + t.testcase.err <- gen.ErrTimeout + return + } + + t.testcase.err <- nil +} + +// TestFragmentSendCompressed sends a large compressed message that still exceeds FragmentSize. +func (t *t10) TestFragmentSendCompressed(input any) { + defer func() { t.testcase = nil }() + + pid, err := t.RemoteSpawn(t.remote, "t10pong", gen.ProcessOptions{}) + if err != nil { + t.testcase.err <- err + return + } + + t10pongCh = make(chan any, 1) + + // large enough that even compressed it exceeds FragmentSize=1000 + pingvalue := lib.RandomString(10000) + + t.SetCompression(true) + defer t.SetCompression(false) + + if err := t.Send(pid, pingvalue); err != nil { + t.testcase.err <- err + return + } + + select { + case pong := <-t10pongCh: + if reflect.DeepEqual(pingvalue, pong) == false { + t.testcase.err <- fmt.Errorf("pong value mismatch (compressed+fragmented)") + return + } + case <-time.NewTimer(5 * time.Second).C: + t.testcase.err <- gen.ErrTimeout + return + } + + t.testcase.err <- nil +} + +// TestFragmentSendImportant sends a large important message. +// ACK must arrive after full reassembly. +func (t *t10) TestFragmentSendImportant(input any) { + defer func() { t.testcase = nil }() + + pid, err := t.RemoteSpawn(t.remote, "t10pong", gen.ProcessOptions{}) + if err != nil { + t.testcase.err <- err + return + } + + t10pongCh = make(chan any, 1) + + pingvalue := lib.RandomString(5000) + + if err := t.SendImportant(pid, pingvalue); err != nil { + t.testcase.err <- err + return + } + + select { + case pong := <-t10pongCh: + if reflect.DeepEqual(pingvalue, pong) == false { + t.testcase.err <- fmt.Errorf("pong value mismatch (important)") + return + } + case <-time.NewTimer(5 * time.Second).C: + t.testcase.err <- gen.ErrTimeout + return + } + + t.testcase.err <- nil +} + +// TestFragmentSendSmall sends a message smaller than FragmentSize. +// Should NOT be fragmented, just sent normally. +func (t *t10) TestFragmentSendSmall(input any) { + defer func() { t.testcase = nil }() + + pid, err := t.RemoteSpawn(t.remote, "t10pong", gen.ProcessOptions{}) + if err != nil { + t.testcase.err <- err + return + } + + t10pongCh = make(chan any, 1) + + // small message, no fragmentation + pingvalue := "hello" + + if err := t.Send(pid, pingvalue); err != nil { + t.testcase.err <- err + return + } + + select { + case pong := <-t10pongCh: + if reflect.DeepEqual(pingvalue, pong) == false { + t.testcase.err <- fmt.Errorf("pong value mismatch (small)") + return + } + case <-time.NewTimer(5 * time.Second).C: + t.testcase.err <- gen.ErrTimeout + return + } + + t.testcase.err <- nil +} + +func TestT10Fragmentation(t *testing.T) { + options1 := gen.NodeOptions{} + options1.Network.Cookie = "fragtest" + options1.Network.FragmentSize = 1000 + options1.Log.DefaultLogger.Disable = false + options1.Log.Level = gen.LogLevelTrace + node1, err := ergo.StartNode("distT10node1Frag@localhost", options1) + if err != nil { + t.Fatal(err) + } + defer node1.Stop() + + options2 := gen.NodeOptions{} + options2.Network.Cookie = "fragtest" + options2.Network.FragmentSize = 1000 + options2.Log.DefaultLogger.Disable = false + options2.Log.Level = gen.LogLevelTrace + node2, err := ergo.StartNode("distT10node2Frag@localhost", options2) + if err != nil { + t.Fatal(err) + } + defer node2.Stop() + + if err := node2.Network().EnableSpawn("t10pong", factory_t10pong); err != nil { + t.Fatal(err) + } + + // establish connection + if _, err := node1.Network().GetNode(node2.Name()); err != nil { + t.Fatal(err) + } + + pid, err := node1.Spawn(factory_t10, gen.ProcessOptions{}, node2.Name()) + if err != nil { + panic(err) + } + + t10cases := []*testcase{ + {"TestFragmentSendSmall", nil, nil, make(chan error)}, + {"TestFragmentSendOrdered", nil, nil, make(chan error)}, + {"TestFragmentSendUnordered", nil, nil, make(chan error)}, + {"TestFragmentSendCompressed", nil, nil, make(chan error)}, + {"TestFragmentSendImportant", nil, nil, make(chan error)}, + } + for _, tc := range t10cases { + t.Run(tc.name, func(t *testing.T) { + node1.Send(pid, tc) + if err := tc.wait(10); err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/testing/tests/002_distributed/t011_fragmentation_load_test.go b/testing/tests/002_distributed/t011_fragmentation_load_test.go new file mode 100644 index 000000000..ac9d82f42 --- /dev/null +++ b/testing/tests/002_distributed/t011_fragmentation_load_test.go @@ -0,0 +1,323 @@ +package distributed + +import ( + "fmt" + "sync" + "sync/atomic" + "testing" + "time" + + "ergo.services/ergo" + "ergo.services/ergo/act" + "ergo.services/ergo/gen" + "ergo.services/ergo/lib" +) + +// t11receiver counts received messages and signals when target is reached +type t11receiver struct { + act.Actor + + target int64 + count atomic.Int64 + done chan struct{} + mismatch atomic.Int64 +} + +var ( + t11done chan struct{} + t11target int64 + t11count atomic.Int64 + t11mismatch atomic.Int64 +) + +func factory_t11receiver() gen.ProcessBehavior { + return &t11receiver{} +} + +func (t *t11receiver) Init(args ...any) error { + return nil +} + +func (t *t11receiver) HandleMessage(from gen.PID, message any) error { + s, ok := message.(string) + if ok == false { + t11mismatch.Add(1) + return nil + } + // verify payload integrity: first 10 chars are the expected length + expected := fmt.Sprintf("%010d", len(s)) + if len(s) < 10 || s[:10] != expected { + t11mismatch.Add(1) + return nil + } + + n := t11count.Add(1) + if n >= t11target { + select { + case t11done <- struct{}{}: + default: + } + } + return nil +} + +// t11sender sends N messages of given size to remote pid +type t11sender struct { + act.Actor +} + +func factory_t11sender() gen.ProcessBehavior { + return &t11sender{} +} + +type t11sendJob struct { + target gen.PID + size int + count int + noOrder bool + done chan error +} + +func (t *t11sender) HandleMessage(from gen.PID, message any) error { + job, ok := message.(*t11sendJob) + if ok == false { + return nil + } + + if job.noOrder { + t.SetKeepNetworkOrder(false) + } + + for i := 0; i < job.count; i++ { + // create payload with size prefix for integrity check + s := lib.RandomString(job.size) + prefix := fmt.Sprintf("%010d", len(s)) + s = prefix + s[10:] + + if err := t.Send(job.target, s); err != nil { + job.done <- fmt.Errorf("send error at msg %d: %w", i, err) + return nil + } + } + job.done <- nil + return nil +} + +func TestT11FragmentationLoad(t *testing.T) { + t.Run("OrderedConcurrent", testFragLoadOrderedConcurrent) + t.Run("UnorderedConcurrent", testFragLoadUnorderedConcurrent) + t.Run("MixedOrderConcurrent", testFragLoadMixedConcurrent) +} + +// 10 senders, each sends 100 ordered large messages +func testFragLoadOrderedConcurrent(t *testing.T) { + node1, node2, receiverPID := setupFragLoadNodes(t, "Ordered") + defer node1.Stop() + defer node2.Stop() + + numSenders := 10 + msgsPerSender := 100 + msgSize := 5000 // ~6 fragments each at FragmentSize=1000 + totalMsgs := numSenders * msgsPerSender + + t11done = make(chan struct{}, 1) + t11target = int64(totalMsgs) + t11count.Store(0) + t11mismatch.Store(0) + + // spawn senders and fire jobs + var wg sync.WaitGroup + for i := 0; i < numSenders; i++ { + wg.Add(1) + go func() { + defer wg.Done() + pid, err := node1.Spawn(factory_t11sender, gen.ProcessOptions{}) + if err != nil { + t.Errorf("spawn sender: %v", err) + return + } + job := &t11sendJob{ + target: receiverPID, + size: msgSize, + count: msgsPerSender, + noOrder: false, + done: make(chan error, 1), + } + node1.Send(pid, job) + if err := <-job.done; err != nil { + t.Errorf("sender error: %v", err) + } + }() + } + + // wait for all sends to complete + wg.Wait() + + // wait for all messages to be received + select { + case <-t11done: + case <-time.After(30 * time.Second): + t.Fatalf("timeout: received %d/%d messages", t11count.Load(), totalMsgs) + } + + if m := t11mismatch.Load(); m > 0 { + t.Fatalf("payload integrity errors: %d", m) + } + t.Logf("OK: %d messages delivered, %d fragments each (~%d total fragments)", + totalMsgs, msgSize/984+1, totalMsgs*(msgSize/984+1)) +} + +// 10 senders, each sends 100 unordered large messages +func testFragLoadUnorderedConcurrent(t *testing.T) { + node1, node2, receiverPID := setupFragLoadNodes(t, "Unordered") + defer node1.Stop() + defer node2.Stop() + + numSenders := 10 + msgsPerSender := 100 + msgSize := 5000 + totalMsgs := numSenders * msgsPerSender + + t11done = make(chan struct{}, 1) + t11target = int64(totalMsgs) + t11count.Store(0) + t11mismatch.Store(0) + + var wg sync.WaitGroup + for i := 0; i < numSenders; i++ { + wg.Add(1) + go func() { + defer wg.Done() + pid, err := node1.Spawn(factory_t11sender, gen.ProcessOptions{}) + if err != nil { + t.Errorf("spawn sender: %v", err) + return + } + job := &t11sendJob{ + target: receiverPID, + size: msgSize, + count: msgsPerSender, + noOrder: true, + done: make(chan error, 1), + } + node1.Send(pid, job) + if err := <-job.done; err != nil { + t.Errorf("sender error: %v", err) + } + }() + } + + wg.Wait() + + select { + case <-t11done: + case <-time.After(30 * time.Second): + t.Fatalf("timeout: received %d/%d messages", t11count.Load(), totalMsgs) + } + + if m := t11mismatch.Load(); m > 0 { + t.Fatalf("payload integrity errors: %d", m) + } + t.Logf("OK: %d messages delivered (unordered, shared assembly)", totalMsgs) +} + +// 10 senders: 5 ordered + 5 unordered, mixed sizes +func testFragLoadMixedConcurrent(t *testing.T) { + node1, node2, receiverPID := setupFragLoadNodes(t, "Mixed") + defer node1.Stop() + defer node2.Stop() + + numSenders := 10 + msgsPerSender := 100 + totalMsgs := numSenders * msgsPerSender + + t11done = make(chan struct{}, 1) + t11target = int64(totalMsgs) + t11count.Store(0) + t11mismatch.Store(0) + + var wg sync.WaitGroup + for i := 0; i < numSenders; i++ { + wg.Add(1) + idx := i + go func() { + defer wg.Done() + pid, err := node1.Spawn(factory_t11sender, gen.ProcessOptions{}) + if err != nil { + t.Errorf("spawn sender: %v", err) + return + } + // odd senders: unordered, larger messages + // even senders: ordered, smaller messages + noOrder := idx%2 == 1 + size := 3000 + if noOrder { + size = 8000 + } + job := &t11sendJob{ + target: receiverPID, + size: size, + count: msgsPerSender, + noOrder: noOrder, + done: make(chan error, 1), + } + node1.Send(pid, job) + if err := <-job.done; err != nil { + t.Errorf("sender error: %v", err) + } + }() + } + + wg.Wait() + + select { + case <-t11done: + case <-time.After(30 * time.Second): + t.Fatalf("timeout: received %d/%d messages", t11count.Load(), totalMsgs) + } + + if m := t11mismatch.Load(); m > 0 { + t.Fatalf("payload integrity errors: %d", m) + } + t.Logf("OK: %d messages delivered (mixed ordered/unordered)", totalMsgs) +} + +func setupFragLoadNodes(t *testing.T, suffix string) (gen.Node, gen.Node, gen.PID) { + t.Helper() + + options1 := gen.NodeOptions{} + options1.Network.Cookie = "fragload" + options1.Network.FragmentSize = 1000 + options1.Log.DefaultLogger.Disable = true + node1, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11node1%s@localhost", suffix)), options1) + if err != nil { + t.Fatal(err) + } + + options2 := gen.NodeOptions{} + options2.Network.Cookie = "fragload" + options2.Network.FragmentSize = 1000 + options2.Log.DefaultLogger.Disable = true + node2, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11node2%s@localhost", suffix)), options2) + if err != nil { + node1.Stop() + t.Fatal(err) + } + + // spawn receiver on node2 + receiverPID, err := node2.Spawn(factory_t11receiver, gen.ProcessOptions{}) + if err != nil { + node1.Stop() + node2.Stop() + t.Fatal(err) + } + + // establish connection + if _, err := node1.Network().GetNode(node2.Name()); err != nil { + node1.Stop() + node2.Stop() + t.Fatal(err) + } + + return node1, node2, receiverPID +} From ce01d2e382f60f83ab51ef61e2d629e918c455f7 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 10 Mar 2026 13:34:09 +0100 Subject: [PATCH 045/122] fix msg/bytes counters for fragmented messages --- net/proto/connection.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/proto/connection.go b/net/proto/connection.go index 049019e39..b56a200ce 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -1689,8 +1689,10 @@ func (c *connection) serve(conn net.Conn, tail []byte) { recvN++ - atomic.AddUint64(&c.messagesIn, 1) atomic.AddUint64(&c.bytesIn, uint64(buf.Len())) + if buf.B[7] != protoMessageF { + atomic.AddUint64(&c.messagesIn, 1) + } // TODO // c.transitIn @@ -3239,7 +3241,6 @@ func (c *connection) sendFragmented(buf *lib.Buffer, order uint8) error { c.pool_mutex.RUnlock() } - fragLen := uint64(frag.Len()) _, err := pi.fl.Write(frag.B) lib.ReleaseBuffer(frag) if err != nil { @@ -3248,10 +3249,11 @@ func (c *connection) sendFragmented(buf *lib.Buffer, order uint8) error { return err } - atomic.AddUint64(&c.messagesOut, 1) - atomic.AddUint64(&c.bytesOut, fragLen) + atomic.AddUint64(&c.bytesOut, uint64(16+chunkSize)) } + atomic.AddUint64(&c.messagesOut, 1) + lib.ReleaseBuffer(buf) c.fragmentsSent.Add(uint64(totalFragments)) @@ -3346,6 +3348,7 @@ func (c *connection) handleFragmentOrdered(buf *lib.Buffer, assemblies map[uint3 } c.fragmentMessagesRecv.Add(1) + atomic.AddUint64(&c.messagesIn, 1) if lib.Trace() { c.log.Trace("fragment assembly complete: seq=%d, %d bytes, %d fragments", @@ -3448,6 +3451,7 @@ func (c *connection) handleFragmentUnordered(buf *lib.Buffer) *lib.Buffer { } c.fragmentMessagesRecv.Add(1) + atomic.AddUint64(&c.messagesIn, 1) if lib.Trace() { c.log.Trace("fragment assembly complete: seq=%d, %d bytes, %d fragments", From c2d8d8287c0a928ab1c20bb94f2a9da5d6dd3e7d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 10 Mar 2026 14:04:00 +0100 Subject: [PATCH 046/122] update README.md --- CHANGELOG.md | 2 ++ README.md | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22d7ea314..402088a91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed **silent data loss on connection pool write failure** - a transient write error could permanently break a pool item's write path without detection, causing all subsequent messages to be silently dropped while the connection appeared healthy * Added **software keepalive** for inter-node connections. Application-level heartbeat detects silent failures that TCP keepalive cannot: stuck processes, broken flushers, goroutine starvation. Each side advertises its period during handshake (8 bits in `NetworkFlags`); receiver uses peer's period for timeout. Enabled by default (15s period, 3 misses, 45s timeout). Configure via `NetworkFlags.EnableSoftwareKeepAlive` and `NetworkOptions.SoftwareKeepAliveMisses`. See [Network Stack](https://docs.ergo.services/networking/network-stack#software-keepalive) documentation * Added **handshake deadline** (5s) to prevent hung handshakes from blocking connection goroutines indefinitely +* Added **message fragmentation** for large messages. Messages exceeding the fragment size (default 65000 bytes) are automatically split for transmission and reassembled on the receiving side. Works with compression, important delivery, and all message types. With `KeepNetworkOrder` disabled, fragments are distributed across all TCP connections in the pool for maximum throughput. Both nodes must enable `EnableFragmentation` flag (enabled by default). Configure via `NetworkOptions.FragmentSize`, `FragmentTimeout`, `MaxFragmentAssemblies`. See [Network Stack](https://docs.ergo.services/networking/network-stack#message-fragmentation) documentation +* Fixed **important delivery use-after-release** - reference ID for acknowledgment was read from buffer after it was returned to the pool, causing corrupted ACK responses under load. Affected `SendImportant` for PID, ProcessID, and Alias targets #### [v3.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.320) 2026-02-04 [tag version v1.999.320] #### diff --git a/README.md b/README.md index 69e3995fc..6a91bd0cf 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,10 @@ Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file. * Added **handshake deadline** (5s) to prevent hung handshakes from blocking connection goroutines indefinitely +* Added **message fragmentation** for large messages. Messages exceeding the fragment size (default 65000 bytes) are automatically split and reassembled. With `KeepNetworkOrder` disabled, fragments use all TCP connections for maximum throughput. See [Network Stack](https://docs.ergo.services/networking/network-stack#message-fragmentation) documentation + +* Fixed **important delivery use-after-release** - reference ID read from buffer after pool release, causing corrupted ACK responses + ### Development and debugging ### To enable Golang profiler just add `--tags pprof` in your `go run` or `go build` (profiler runs at From 83254b31cb813ea3e4f7d28545f6da57d6b7d093 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 10 Mar 2026 15:42:22 +0100 Subject: [PATCH 047/122] add compression metrics --- gen/network.go | 13 +++++++++++++ net/proto/connection.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/gen/network.go b/gen/network.go index 236673fd6..40b498878 100644 --- a/gen/network.go +++ b/gen/network.go @@ -573,6 +573,19 @@ type RemoteNodeInfo struct { FragmentMessagesRecv uint64 // FragmentTimeouts is the total number of fragment assemblies that timed out. FragmentTimeouts uint64 + + // CompressedSent is the total number of messages compressed on send. + CompressedSent uint64 + // CompressedBytesSent is the total bytes after compression (wire size). + CompressedBytesSent uint64 + // CompressedOrigBytesSent is the total bytes before compression (original size). + CompressedOrigBytesSent uint64 + // DecompressedRecv is the total number of messages decompressed on receive. + DecompressedRecv uint64 + // DecompressedBytesRecv is the total bytes before decompression (wire size). + DecompressedBytesRecv uint64 + // DecompressedOrigRecv is the total bytes after decompression (original size). + DecompressedOrigRecv uint64 } // AcceptorOptions configures a network listener (acceptor) for incoming connections. diff --git a/net/proto/connection.go b/net/proto/connection.go index b56a200ce..de6f47bba 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -94,6 +94,14 @@ type connection struct { fragmentMessagesRecv atomic.Uint64 fragmentTimeouts atomic.Uint64 + // compression statistics + compressedSent atomic.Uint64 // messages compressed on send + compressedBytesSent atomic.Uint64 // bytes after compression (wire) + compressedOrigBytesSent atomic.Uint64 // bytes before compression (original) + decompressedRecv atomic.Uint64 // messages decompressed on receive + decompressedBytesRecv atomic.Uint64 // bytes before decompression (wire) + decompressedOrigRecv atomic.Uint64 // bytes after decompression (original) + order uint32 terminated bool wg sync.WaitGroup @@ -166,6 +174,13 @@ func (c *connection) Info() gen.RemoteNodeInfo { FragmentsReceived: c.fragmentsReceived.Load(), FragmentMessagesRecv: c.fragmentMessagesRecv.Load(), FragmentTimeouts: c.fragmentTimeouts.Load(), + + CompressedSent: c.compressedSent.Load(), + CompressedBytesSent: c.compressedBytesSent.Load(), + CompressedOrigBytesSent: c.compressedOrigBytesSent.Load(), + DecompressedRecv: c.decompressedRecv.Load(), + DecompressedBytesRecv: c.decompressedBytesRecv.Load(), + DecompressedOrigRecv: c.decompressedOrigRecv.Load(), } return info } @@ -2687,6 +2702,9 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC, qIdx int) { c.log.Error("unable to decompress message (gzip), ignored: %s", err) continue } + c.decompressedRecv.Add(1) + c.decompressedBytesRecv.Add(uint64(buf.Len())) + c.decompressedOrigRecv.Add(uint64(dbuf.Len())) lib.ReleaseBuffer(buf) buf = dbuf goto re @@ -2697,6 +2715,9 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC, qIdx int) { c.log.Error("unable to decompress message (lzw), ignored: %s", err) continue } + c.decompressedRecv.Add(1) + c.decompressedBytesRecv.Add(uint64(buf.Len())) + c.decompressedOrigRecv.Add(uint64(dbuf.Len())) lib.ReleaseBuffer(buf) buf = dbuf goto re @@ -2707,6 +2728,9 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC, qIdx int) { c.log.Error("unable to decompress message (zlib), ignored: %s", err) continue } + c.decompressedRecv.Add(1) + c.decompressedBytesRecv.Add(uint64(buf.Len())) + c.decompressedOrigRecv.Add(uint64(dbuf.Len())) lib.ReleaseBuffer(buf) buf = dbuf goto re @@ -3132,6 +3156,10 @@ func (c *connection) send(buf *lib.Buffer, order uint8, compression gen.Compress zbuf.B[7] = protoMessageZ zbuf.B[8] = compression.Type.ID() + c.compressedSent.Add(1) + c.compressedOrigBytesSent.Add(uint64(buf.Len())) + c.compressedBytesSent.Add(uint64(zbuf.Len())) + lib.ReleaseBuffer(buf) buf = zbuf } From 1c6bb55455038835193d34a2ad58297d90a19d11 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 11 Mar 2026 09:59:53 +0100 Subject: [PATCH 048/122] update docs --- docs/extra-library/actors/metrics.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 56267d343..59bf8ca2d 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -118,7 +118,7 @@ Log message count by level (`trace`, `debug`, `info`, `warning`, `error`, `panic ### Network Metrics -Connected node count, per-node uptime, message and byte rates (in/out per remote node), cumulative connections established/lost, and per-acceptor handshake error count. +Connected node count, per-node uptime, message and byte rates (in/out per remote node), cumulative connections established/lost, and per-acceptor handshake error count. Fragmentation metrics per remote node: fragments sent/received, fragmented messages sent/reassembled, assembly timeouts. Compression metrics per remote node: compressed messages sent, bytes before/after compression, decompressed messages received, bytes before/after decompression. Compression ratio (`original / compressed`) reveals whether compression is effective for each connection. ### Mailbox Latency Metrics @@ -136,6 +136,7 @@ Always active. Includes: - **Init time** -- ProcessInit duration. Max and top-N. - **Throughput** -- messages in/out per process (top-N) and node-level aggregates. - **Wakeups and drains** -- wakeup count and drain ratio (messages processed per wakeup). Drain ratio distinguishes between slow callbacks (drain ~1) and high-throughput batching (drain ~100) at the same utilization level. +- **Liveness** -- detects processes stuck in blocking calls. Computed as `RunningTime / (Uptime * MailboxLatency)`. A healthy process has RunningTime growing with activity (high score). A process blocked in a mutex, channel, or IO has RunningTime frozen while uptime and latency keep growing (score drops over time). Zombie processes are excluded (detected separately). Bottom-N surfaces the most stuck processes. Requires `-tags=latency`. ### Event Metrics @@ -286,7 +287,7 @@ The metrics package includes a pre-built Grafana dashboard (`ergo-cluster.json`) Import it in Grafana: Dashboards > Import > upload `ergo-cluster.json` > select your Prometheus data source. The `$node` dropdown at the top filters all panels by selected nodes. -The dashboard is organized top-down: Summary row at the top for cluster health at a glance, then Mailbox Latency and Depth for backpressure analysis, then collapsed rows for Events, Process Activity, Processes, Resources, Logging, and Network. Each row focuses on a specific aspect of cluster behavior and can be expanded when investigating issues. +The dashboard is organized top-down: Summary row at the top for cluster health at a glance, then Mailbox Latency and Depth for backpressure analysis, then collapsed rows for Events, Process Activity, Processes, Resources, Logging, and Network. The Network row includes compression overview (ratio, rate, percentage), per-node compression ratio, fragmentation rates (cluster and per-node), connectivity strength, and connection events. Each row focuses on a specific aspect of cluster behavior and can be expanded when investigating issues. For detailed panel descriptions, see the [metrics actor README](https://github.com/ergo-services/actor). From 402f61f3f971f4591d6787717e42ffc44890c02a Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 17 Mar 2026 09:36:06 +0100 Subject: [PATCH 049/122] sync --- app/system/inspect/application_list.go | 8 +- app/system/inspect/application_tree.go | 8 +- app/system/inspect/connection.go | 8 +- app/system/inspect/connection_list.go | 140 ++++++++++++++++++ app/system/inspect/event_list.go | 164 +++++++++++++++++++++ app/system/inspect/inspect.go | 155 +++++++++++++++++++- app/system/inspect/log.go | 99 ++++++------- app/system/inspect/message.go | 180 ++++++++++++++++++----- app/system/inspect/meta.go | 18 ++- app/system/inspect/meta_state.go | 10 +- app/system/inspect/network.go | 8 +- app/system/inspect/node.go | 19 ++- app/system/inspect/process.go | 18 ++- app/system/inspect/process_list.go | 37 ++++- app/system/inspect/process_range.go | 191 +++++++++++++++++++++++++ app/system/inspect/process_state.go | 10 +- docs/basics/logging.md | 4 +- gen/network.go | 3 + gen/node.go | 42 ++++-- net/edf/init.go | 43 +++++- net/handshake/accept.go | 2 + net/handshake/start.go | 2 + net/handshake/types.go | 1 + net/proto/connection.go | 2 + net/proto/enp.go | 1 + node/application.go | 47 +++--- node/node.go | 137 ++++++++++++++++-- testing/unit/node.go | 36 ++++- 28 files changed, 1204 insertions(+), 189 deletions(-) create mode 100644 app/system/inspect/connection_list.go create mode 100644 app/system/inspect/event_list.go create mode 100644 app/system/inspect/process_range.go diff --git a/app/system/inspect/application_list.go b/app/system/inspect/application_list.go index 42cb5967a..d07fb604c 100644 --- a/app/system/inspect/application_list.go +++ b/app/system/inspect/application_list.go @@ -16,6 +16,7 @@ type application_list struct { token gen.Ref generating bool + loopID uint64 event gen.Atom } @@ -30,7 +31,7 @@ func (ial *application_list) Init(args ...any) error { func (ial *application_list) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ial.generating == false { + if m.id != ial.loopID || ial.generating == false { ial.Log().Debug("generating canceled") break // cancelled } @@ -60,7 +61,7 @@ func (ial *application_list) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - ial.SendAfter(ial.PID(), generate{}, inspectApplicationListPeriod) + ial.SendAfter(ial.PID(), generate{id: ial.loopID}, inspectApplicationListPeriod) case requestInspect: response := ResponseInspectApplicationList{ @@ -98,7 +99,8 @@ func (ial *application_list) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ial.Log().Debug("got first subscriber. start generating events...") - ial.Send(ial.PID(), generate{}) + ial.loopID++ + ial.Send(ial.PID(), generate{id: ial.loopID}) ial.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/application_tree.go b/app/system/inspect/application_tree.go index 68a032c37..04f62a0d4 100644 --- a/app/system/inspect/application_tree.go +++ b/app/system/inspect/application_tree.go @@ -18,6 +18,7 @@ type application_tree struct { application gen.Atom limit int generating bool + loopID uint64 event gen.Atom } @@ -34,7 +35,7 @@ func (iat *application_tree) Init(args ...any) error { func (iat *application_tree) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if iat.generating == false { + if m.id != iat.loopID || iat.generating == false { iat.Log().Debug("generating canceled") break // cancelled } @@ -56,7 +57,7 @@ func (iat *application_tree) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - iat.SendAfter(iat.PID(), generate{}, inspectApplicationTreePeriod) + iat.SendAfter(iat.PID(), generate{id: iat.loopID}, inspectApplicationTreePeriod) case requestInspect: response := ResponseInspectApplicationTree{ @@ -94,7 +95,8 @@ func (iat *application_tree) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber iat.Log().Debug("got first subscriber. start generating events...") - iat.Send(iat.PID(), generate{}) + iat.loopID++ + iat.Send(iat.PID(), generate{id: iat.loopID}) iat.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/connection.go b/app/system/inspect/connection.go index 85393fdd1..92f7dac84 100644 --- a/app/system/inspect/connection.go +++ b/app/system/inspect/connection.go @@ -17,6 +17,7 @@ type connection struct { event gen.Atom generating bool + loopID uint64 remote gen.Atom } @@ -32,7 +33,7 @@ func (ic *connection) Init(args ...any) error { func (ic *connection) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ic.generating == false { + if m.id != ic.loopID || ic.generating == false { ic.Log().Debug("generating canceled") break // cancelled } @@ -60,7 +61,7 @@ func (ic *connection) HandleMessage(from gen.PID, message any) error { if ev.Disconnected { return gen.TerminateReasonNormal } - ic.SendAfter(ic.PID(), generate{}, inspectNetworkPeriod) + ic.SendAfter(ic.PID(), generate{id: ic.loopID}, inspectNetworkPeriod) case requestInspect: response := ResponseInspectConnection{ @@ -106,7 +107,8 @@ func (ic *connection) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ic.Log().Debug("got first subscriber. start generating events...") - ic.Send(ic.PID(), generate{}) + ic.loopID++ + ic.Send(ic.PID(), generate{id: ic.loopID}) ic.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/connection_list.go b/app/system/inspect/connection_list.go new file mode 100644 index 000000000..507014bd9 --- /dev/null +++ b/app/system/inspect/connection_list.go @@ -0,0 +1,140 @@ +package inspect + +import ( + "fmt" + "slices" + "strings" + + "ergo.services/ergo/act" + "ergo.services/ergo/gen" +) + +func factory_connection_list() gen.ProcessBehavior { + return &connection_list{} +} + +type connection_list struct { + act.Actor + token gen.Ref + + name string + limit int + hash string + generating bool + loopID uint64 + event gen.Atom +} + +func (icl *connection_list) Init(args ...any) error { + icl.name = args[0].(string) + icl.limit = args[1].(int) + icl.hash = args[2].(string) + + icl.Log().SetLogger("default") + icl.Log().Debug("connection list inspector started. name=%q limit=%d", icl.name, icl.limit) + icl.Send(icl.PID(), register{}) + return nil +} + +func (icl *connection_list) HandleMessage(from gen.PID, message any) error { + switch m := message.(type) { + case generate: + if m.id != icl.loopID || icl.generating == false { + break + } + + networkInfo, err := icl.Node().Network().Info() + if err != nil { + return err + } + + nameLower := strings.ToLower(icl.name) + var connections []gen.RemoteNodeInfo + + // sort node names for stable output + slices.Sort(networkInfo.Nodes) + + for _, n := range networkInfo.Nodes { + if nameLower != "" { + if strings.Contains(strings.ToLower(string(n)), nameLower) == false { + continue + } + } + + remote, rerr := icl.Node().Network().Node(n) + if rerr != nil { + continue + } + + connections = append(connections, remote.Info()) + + if icl.limit > 0 && len(connections) >= icl.limit { + break + } + } + + ev := MessageInspectConnectionList{ + Node: icl.Node().Name(), + Connections: connections, + } + + if err := icl.SendEvent(icl.event, icl.token, ev); err != nil { + icl.Log().Error("unable to send event %q: %s", icl.event, err) + return gen.TerminateReasonNormal + } + + icl.SendAfter(icl.PID(), generate{id: icl.loopID}, inspectConnectionListPeriod) + + case requestInspect: + response := ResponseInspectConnectionList{ + Event: gen.Event{ + Name: icl.event, + Node: icl.Node().Name(), + }, + } + icl.SendResponse(m.pid, m.ref, response) + + case register: + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + icl.event = gen.Atom(fmt.Sprintf("%s_%s", inspectConnectionList, icl.hash)) + token, err := icl.RegisterEvent(icl.event, eopts) + if err != nil { + icl.Log().Error("unable to register event: %s", err) + return err + } + icl.Log().Info("registered event %s", icl.event) + icl.token = token + icl.SendAfter(icl.PID(), shutdown{}, inspectConnectionListIdlePeriod) + + case shutdown: + if icl.generating { + break + } + return gen.TerminateReasonNormal + + case gen.MessageEventStart: + icl.Log().Debug("got first subscriber. start generating events...") + icl.loopID++ + icl.Send(icl.PID(), generate{id: icl.loopID}) + icl.generating = true + + case gen.MessageEventStop: + icl.Log().Debug("no subscribers. stop generating") + if icl.generating { + icl.generating = false + icl.SendAfter(icl.PID(), shutdown{}, inspectConnectionListIdlePeriod) + } + + default: + icl.Log().Error("unknown message (ignored) %#v", message) + } + + return nil +} + +func (icl *connection_list) Terminate(reason error) { + icl.Log().Debug("connection list inspector terminated: %s", reason) +} diff --git a/app/system/inspect/event_list.go b/app/system/inspect/event_list.go new file mode 100644 index 000000000..888f9d722 --- /dev/null +++ b/app/system/inspect/event_list.go @@ -0,0 +1,164 @@ +package inspect + +import ( + "fmt" + "strings" + + "ergo.services/ergo/act" + "ergo.services/ergo/gen" +) + +func factory_event_list() gen.ProcessBehavior { + return &event_list{} +} + +type event_list struct { + act.Actor + token gen.Ref + + name string + notify int + buffered int + minSubscribers int64 + limit int + hash string + + generating bool + loopID uint64 + event gen.Atom +} + +func (iel *event_list) Init(args ...any) error { + iel.name = args[0].(string) + iel.notify = args[1].(int) + iel.buffered = args[2].(int) + iel.minSubscribers = args[3].(int64) + iel.limit = args[4].(int) + iel.hash = args[5].(string) + + iel.Log().SetLogger("default") + iel.Log().Debug("event list inspector started. name=%q notify=%d buffered=%d minSubs=%d limit=%d", + iel.name, iel.notify, iel.buffered, iel.minSubscribers, iel.limit) + iel.Send(iel.PID(), register{}) + return nil +} + +func (iel *event_list) HandleMessage(from gen.PID, message any) error { + switch m := message.(type) { + case generate: + if m.id != iel.loopID || iel.generating == false { + iel.Log().Debug("generating canceled") + break + } + iel.Log().Debug("generating event") + + var events []gen.EventInfo + nameLower := strings.ToLower(iel.name) + + iel.Node().EventRangeInfo(func(info gen.EventInfo) bool { + if nameLower != "" { + if strings.Contains(strings.ToLower(string(info.Event.Name)), nameLower) == false { + return true + } + } + if iel.notify == 1 { + if info.Notify == false { + return true + } + } + if iel.notify == -1 { + if info.Notify == true { + return true + } + } + if iel.buffered == 1 { + if info.BufferSize == 0 { + return true + } + } + if iel.buffered == -1 { + if info.BufferSize > 0 { + return true + } + } + if iel.minSubscribers > 0 { + if info.Subscribers < iel.minSubscribers { + return true + } + } + + events = append(events, info) + + if iel.limit > 0 && len(events) >= iel.limit { + return false + } + return true + }) + + ev := MessageInspectEventList{ + Node: iel.Node().Name(), + Events: events, + } + + if err := iel.SendEvent(iel.event, iel.token, ev); err != nil { + iel.Log().Error("unable to send event %q: %s", iel.event, err) + return gen.TerminateReasonNormal + } + + iel.SendAfter(iel.PID(), generate{id: iel.loopID}, inspectEventListPeriod) + + case requestInspect: + response := ResponseInspectEventList{ + Event: gen.Event{ + Name: iel.event, + Node: iel.Node().Name(), + }, + } + iel.SendResponse(m.pid, m.ref, response) + iel.Log().Debug("sent response for the inspect event list request to: %s", m.pid) + + case register: + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + iel.event = gen.Atom(fmt.Sprintf("%s_%s", inspectEventList, iel.hash)) + token, err := iel.RegisterEvent(iel.event, eopts) + if err != nil { + iel.Log().Error("unable to register event: %s", err) + return err + } + iel.Log().Info("registered event %s", iel.event) + iel.token = token + iel.SendAfter(iel.PID(), shutdown{}, inspectEventListIdlePeriod) + + case shutdown: + if iel.generating { + iel.Log().Debug("ignore shutdown. generating is active") + break + } + return gen.TerminateReasonNormal + + case gen.MessageEventStart: + iel.Log().Debug("got first subscriber. start generating events...") + iel.loopID++ + iel.Send(iel.PID(), generate{id: iel.loopID}) + iel.generating = true + + case gen.MessageEventStop: + iel.Log().Debug("no subscribers. stop generating") + if iel.generating { + iel.generating = false + iel.SendAfter(iel.PID(), shutdown{}, inspectEventListIdlePeriod) + } + + default: + iel.Log().Error("unknown message (ignored) %#v", message) + } + + return nil +} + +func (iel *event_list) Terminate(reason error) { + iel.Log().Debug("event list inspector terminated: %s", reason) +} diff --git a/app/system/inspect/inspect.go b/app/system/inspect/inspect.go index f85eb7b08..ea3d29968 100644 --- a/app/system/inspect/inspect.go +++ b/app/system/inspect/inspect.go @@ -55,6 +55,18 @@ const ( inspectApplicationTree = "inspect_application_tree" inspectApplicationTreePeriod = time.Second inspectApplicationTreeIdlePeriod = 5 * time.Second + + inspectEventList = "inspect_event_list" + inspectEventListPeriod = time.Second + inspectEventListIdlePeriod = 5 * time.Second + + inspectProcessRange = "inspect_process_range" + inspectProcessRangePeriod = time.Second + inspectProcessRangeIdlePeriod = 5 * time.Second + + inspectConnectionList = "inspect_connection_list" + inspectConnectionListPeriod = time.Second + inspectConnectionListIdlePeriod = 5 * time.Second ) var ( @@ -82,7 +94,8 @@ type requestInspect struct { type register struct{} type shutdown struct{} -type generate struct{} +type generate struct{ id uint64 } +type flushLog struct{ id uint64 } func (i *inspect) Init(args ...any) error { i.Log().SetLogger("default") @@ -146,7 +159,7 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error opts := gen.ProcessOptions{ LinkParent: true, } - if r.Start < 1000 { + if r.Start >= 0 && r.Start < 1000 { r.Start = 1000 } if r.Limit < 1 { @@ -165,6 +178,27 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error i.Send(pname, forward) return nil, nil // no reply + case RequestInspectProcessRange: + opts := gen.ProcessOptions{ + LinkParent: true, + } + if r.Limit < 1 { + r.Limit = 10000 + } + hash := filterHash(r.Name, r.Behavior, r.Application, r.State, r.MinMailbox, r.Limit) + pname := gen.Atom(fmt.Sprintf("%s_%s", inspectProcessRange, hash)) + _, err := i.SpawnRegister(pname, factory_process_range, opts, + r.Name, r.Behavior, r.Application, r.State, r.MinMailbox, r.Limit, hash) + if err != nil && err != gen.ErrTaken { + return err, nil + } + forward := requestInspect{ + pid: from, + ref: ref, + } + i.Send(pname, forward) + return nil, nil // no reply + case RequestInspectProcess: opts := gen.ProcessOptions{ LinkParent: true, @@ -240,6 +274,11 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error // try to spawn node inspector process opts := gen.ProcessOptions{ LinkParent: true, + Compression: gen.Compression{ + Enable: true, + Type: gen.CompressionTypeGZIP, + Level: gen.CompressionBestSpeed, + }, } name := "diwep" @@ -281,6 +320,47 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error i.Send(pname, forward) return nil, nil // no reply + case RequestInspectEventList: + opts := gen.ProcessOptions{ + LinkParent: true, + } + if r.Limit < 1 { + r.Limit = 500 + } + hash := eventListHash(r.Name, r.Notify, r.Buffered, r.MinSubscribers, r.Limit) + pname := gen.Atom(fmt.Sprintf("%s_%s", inspectEventList, hash)) + _, err := i.SpawnRegister(pname, factory_event_list, opts, + r.Name, r.Notify, r.Buffered, r.MinSubscribers, r.Limit, hash) + if err != nil && err != gen.ErrTaken { + return err, nil + } + forward := requestInspect{ + pid: from, + ref: ref, + } + i.Send(pname, forward) + return nil, nil + + case RequestInspectConnectionList: + opts := gen.ProcessOptions{ + LinkParent: true, + } + if r.Limit < 1 { + r.Limit = 100 + } + hash := connectionListHash(r.Name, r.Limit) + pname := gen.Atom(fmt.Sprintf("%s_%s", inspectConnectionList, hash)) + _, err := i.SpawnRegister(pname, factory_connection_list, opts, r.Name, r.Limit, hash) + if err != nil && err != gen.ErrTaken { + return err, nil + } + forward := requestInspect{ + pid: from, + ref: ref, + } + i.Send(pname, forward) + return nil, nil + case RequestInspectApplicationList: opts := gen.ProcessOptions{ LinkParent: true, @@ -355,17 +435,80 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error } return response, nil - case RequestDoSetLogLevelProcess: + case RequestDoSetProcessLogLevel: response := ResponseDoSetLogLevel{ - Error: i.Node().SetLogLevelProcess(r.PID, r.Level), + Error: i.Node().SetProcessLogLevel(r.PID, r.Level), } return response, nil - case RequestDoSetLogLevelMeta: + case RequestDoSetMetaLogLevel: response := ResponseDoSetLogLevel{ - Error: i.Node().SetLogLevelMeta(r.Meta, r.Level), + Error: i.Node().SetMetaLogLevel(r.Meta, r.Level), } return response, nil + + // process settings + + case RequestDoSetProcessSendPriority: + return ResponseDoSet{Error: i.Node().SetProcessSendPriority(r.PID, r.Priority)}, nil + + case RequestDoSetProcessCompression: + return ResponseDoSet{Error: i.Node().SetProcessCompression(r.PID, r.Enabled)}, nil + + case RequestDoSetProcessCompressionType: + return ResponseDoSet{Error: i.Node().SetProcessCompressionType(r.PID, r.Type)}, nil + + case RequestDoSetProcessCompressionLevel: + return ResponseDoSet{Error: i.Node().SetProcessCompressionLevel(r.PID, r.Level)}, nil + + case RequestDoSetProcessCompressionThreshold: + return ResponseDoSet{Error: i.Node().SetProcessCompressionThreshold(r.PID, r.Threshold)}, nil + + case RequestDoSetProcessKeepNetworkOrder: + return ResponseDoSet{Error: i.Node().SetProcessKeepNetworkOrder(r.PID, r.Order)}, nil + + case RequestDoSetProcessImportantDelivery: + return ResponseDoSet{Error: i.Node().SetProcessImportantDelivery(r.PID, r.Important)}, nil + + // meta settings + + case RequestDoSetMetaSendPriority: + return ResponseDoSet{Error: i.Node().SetMetaSendPriority(r.Meta, r.Priority)}, nil + + // app lifecycle + + case RequestDoAppStart: + opts := gen.ApplicationOptions{} + var err error + switch r.Mode { + case gen.ApplicationModeTemporary: + err = i.Node().ApplicationStartTemporary(r.Name, opts) + case gen.ApplicationModeTransient: + err = i.Node().ApplicationStartTransient(r.Name, opts) + case gen.ApplicationModePermanent: + err = i.Node().ApplicationStartPermanent(r.Name, opts) + default: + err = i.Node().ApplicationStart(r.Name, opts) + } + return ResponseDoAppStart{Error: err}, nil + + case RequestDoAppStop: + var err error + if r.Force { + err = i.Node().ApplicationStopForce(r.Name) + } else { + err = i.Node().ApplicationStop(r.Name) + } + return ResponseDoAppStop{Error: err}, nil + + case RequestDoAppUnload: + return ResponseDoAppUnload{Error: i.Node().ApplicationUnload(r.Name)}, nil + + // one-shot inspect + + case RequestDoInspect: + state, err := i.Inspect(r.PID) + return ResponseDoInspect{State: state, Error: err}, nil } i.Log().Error("unsupported request: %#v", request) diff --git a/app/system/inspect/log.go b/app/system/inspect/log.go index 1ffb873f5..b41377f4c 100644 --- a/app/system/inspect/log.go +++ b/app/system/inspect/log.go @@ -2,6 +2,7 @@ package inspect import ( "fmt" + "time" "ergo.services/ergo/act" "ergo.services/ergo/gen" @@ -18,8 +19,12 @@ type log struct { levels []gen.LogLevel generating bool + loopID uint64 + buffer []InspectLogEntry } +const logFlushInterval = time.Second + func (il *log) Init(args ...any) error { il.levels = args[0].([]gen.LogLevel) il.Log().SetLogger("default") @@ -34,6 +39,27 @@ func (il *log) Init(args ...any) error { func (il *log) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { + case flushLog: + if m.id != il.loopID || il.generating == false { + break + } + if len(il.buffer) == 0 { + il.SendAfter(il.PID(), flushLog{id: il.loopID}, logFlushInterval) + break + } + + ev := MessageInspectLog{ + Node: il.Node().Name(), + Entries: il.buffer, + } + il.buffer = nil + + if err := il.SendEvent(il.event, il.token, ev); err != nil { + return gen.TerminateReasonNormal + } + + il.SendAfter(il.PID(), flushLog{id: il.loopID}, logFlushInterval) + case requestInspect: response := ResponseInspectLog{ Event: gen.Event{ @@ -68,7 +94,9 @@ func (il *log) HandleMessage(from gen.PID, message any) error { il.Log().Debug("add this process as a logger") il.Node().LoggerAddPID(il.PID(), il.PID().String(), il.levels...) // we cant use Log() method while this process registered as a logger + il.loopID++ il.generating = true + il.SendAfter(il.PID(), flushLog{id: il.loopID}, logFlushInterval) case gen.MessageEventStop: // no subscribers // unregister this process as a logger @@ -76,6 +104,7 @@ func (il *log) HandleMessage(from gen.PID, message any) error { // now we can use Log() method il.Log().Debug("removed this process as a logger") il.generating = false + il.buffer = nil il.SendAfter(il.PID(), shutdown{}, inspectLogIdlePeriod) } @@ -83,61 +112,33 @@ func (il *log) HandleMessage(from gen.PID, message any) error { } func (il *log) HandleLog(message gen.MessageLog) error { + entry := InspectLogEntry{ + Timestamp: message.Time.UnixNano(), + Level: message.Level, + Message: fmt.Sprintf(message.Format, message.Args...), + Fields: message.Fields, + } + switch m := message.Source.(type) { case gen.MessageLogNode: - // handle message - ev := MessageInspectLogNode{ - Node: m.Node, - Creation: m.Creation, - Timestamp: message.Time.UnixNano(), - Level: message.Level, - Message: fmt.Sprintf(message.Format, message.Args...), - } - if err := il.SendEvent(il.event, il.token, ev); err != nil { - return gen.TerminateReasonNormal - } + entry.Source = "node" + entry.Creation = m.Creation case gen.MessageLogProcess: - // handle message - ev := MessageInspectLogProcess{ - Node: m.Node, - Name: m.Name, - PID: m.PID, - Timestamp: message.Time.UnixNano(), - Level: message.Level, - Message: fmt.Sprintf(message.Format, message.Args...), - } - if err := il.SendEvent(il.event, il.token, ev); err != nil { - return gen.TerminateReasonNormal - } - + entry.Source = "process" + entry.Name = m.Name + entry.PID = m.PID + entry.Behavior = m.Behavior case gen.MessageLogMeta: - // handle message - ev := MessageInspectLogMeta{ - Node: m.Node, - Parent: m.Parent, - Meta: m.Meta, - Timestamp: message.Time.UnixNano(), - Level: message.Level, - Message: fmt.Sprintf(message.Format, message.Args...), - } - - if err := il.SendEvent(il.event, il.token, ev); err != nil { - return gen.TerminateReasonNormal - } + entry.Source = "meta" + entry.Parent = m.Parent + entry.Meta = m.Meta + entry.Behavior = m.Behavior case gen.MessageLogNetwork: - ev := MessageInspectLogNetwork{ - Node: m.Node, - Peer: m.Peer, - Timestamp: message.Time.UnixNano(), - Level: message.Level, - Message: fmt.Sprintf(message.Format, message.Args...), - } - if err := il.SendEvent(il.event, il.token, ev); err != nil { - return gen.TerminateReasonNormal - } + entry.Source = "network" + entry.Peer = gen.Atom(m.Peer.CRC32()) } - // ignore any other log messages - // TODO should we handle them? + + il.buffer = append(il.buffer, entry) return nil } diff --git a/app/system/inspect/message.go b/app/system/inspect/message.go index 547c6b3e9..78da25898 100644 --- a/app/system/inspect/message.go +++ b/app/system/inspect/message.go @@ -9,6 +9,7 @@ type ResponseInspectNode struct { OS string Arch string Cores int + Timezone string Version gen.Version Creation int64 } @@ -48,6 +49,21 @@ type MessageInspectConnection struct { Info gen.RemoteNodeInfo } +// connection list (scoped) + +type RequestInspectConnectionList struct { + Limit int + Name string +} +type ResponseInspectConnectionList struct { + Event gen.Event +} + +type MessageInspectConnectionList struct { + Node gen.Atom + Connections []gen.RemoteNodeInfo +} + // process list type RequestInspectProcessList struct { @@ -72,38 +88,24 @@ type ResponseInspectLog struct { Event gen.Event } -type MessageInspectLogNode struct { - Node gen.Atom - Creation int64 - Timestamp int64 - Level gen.LogLevel - Message string -} - -type MessageInspectLogProcess struct { - Node gen.Atom +type InspectLogEntry struct { + Source string // "node", "process", "network", "meta" Name gen.Atom PID gen.PID - Timestamp int64 - Level gen.LogLevel - Message string -} - -type MessageInspectLogNetwork struct { - Node gen.Atom + Behavior string Peer gen.Atom - Timestamp int64 - Level gen.LogLevel - Message string -} - -type MessageInspectLogMeta struct { - Node gen.Atom Parent gen.PID Meta gen.Alias + Creation int64 Timestamp int64 Level gen.LogLevel Message string + Fields []gen.LogField +} + +type MessageInspectLog struct { + Node gen.Atom + Entries []InspectLogEntry } // process @@ -116,9 +118,8 @@ type ResponseInspectProcess struct { } type MessageInspectProcess struct { - Node gen.Atom - Info gen.ProcessInfo - Terminated bool + Node gen.Atom + Info gen.ProcessInfo } // process state @@ -145,9 +146,8 @@ type ResponseInspectMeta struct { } type MessageInspectMeta struct { - Node gen.Atom - Info gen.MetaInfo - Terminated bool + Node gen.Atom + Info gen.MetaInfo } // meta state @@ -222,17 +222,133 @@ type ResponseDoSetLogLevel struct { } // process -type RequestDoSetLogLevelProcess struct { +type RequestDoSetProcessLogLevel struct { PID gen.PID Level gen.LogLevel } // meta -type RequestDoSetLogLevelMeta struct { +type RequestDoSetMetaLogLevel struct { Meta gen.Alias Level gen.LogLevel } +// do set process settings + +type RequestDoSetProcessSendPriority struct { + PID gen.PID + Priority gen.MessagePriority +} + +type RequestDoSetProcessCompression struct { + PID gen.PID + Enabled bool +} + +type RequestDoSetProcessCompressionType struct { + PID gen.PID + Type gen.CompressionType +} + +type RequestDoSetProcessCompressionLevel struct { + PID gen.PID + Level gen.CompressionLevel +} + +type RequestDoSetProcessCompressionThreshold struct { + PID gen.PID + Threshold int +} + +type RequestDoSetProcessKeepNetworkOrder struct { + PID gen.PID + Order bool +} + +type RequestDoSetProcessImportantDelivery struct { + PID gen.PID + Important bool +} + +// do set meta settings + +type RequestDoSetMetaSendPriority struct { + Meta gen.Alias + Priority gen.MessagePriority +} + +// generic response for do-set operations +type ResponseDoSet struct { + Error error +} + +// do app lifecycle + +type RequestDoAppStart struct { + Name gen.Atom + Mode gen.ApplicationMode +} +type ResponseDoAppStart struct { + Error error +} + +type RequestDoAppStop struct { + Name gen.Atom + Force bool +} +type ResponseDoAppStop struct { + Error error +} + +type RequestDoAppUnload struct { + Name gen.Atom +} +type ResponseDoAppUnload struct { + Error error +} + +// do one-shot inspect + +type RequestDoInspect struct { + PID gen.PID +} +type ResponseDoInspect struct { + State map[string]string + Error error +} + +// process range (full scan with filters) + +type RequestInspectProcessRange struct { + Name string + Behavior string + Application string + State string + MinMailbox uint64 + Limit int +} +type ResponseInspectProcessRange struct { + Event gen.Event +} + +// event list + +type RequestInspectEventList struct { + Limit int + Name string + Notify int // 0=any, 1=yes, -1=no + Buffered int // 0=any, 1=yes, -1=no + MinSubscribers int64 +} +type ResponseInspectEventList struct { + Event gen.Event +} + +type MessageInspectEventList struct { + Node gen.Atom + Events []gen.EventInfo +} + // application list type RequestInspectApplicationList struct{} diff --git a/app/system/inspect/meta.go b/app/system/inspect/meta.go index 7e7dc8e1d..05916abd1 100644 --- a/app/system/inspect/meta.go +++ b/app/system/inspect/meta.go @@ -17,6 +17,7 @@ type meta struct { event gen.Atom generating bool + loopID uint64 meta gen.Alias } @@ -32,14 +33,17 @@ func (im *meta) Init(args ...any) error { func (im *meta) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if im.generating == false { + if m.id != im.loopID || im.generating == false { im.Log().Debug("generating canceled") break // cancelled } im.Log().Debug("generating event") ev := MessageInspectMeta{ - Node: im.Node().Name(), - Terminated: true, + Node: im.Node().Name(), + Info: gen.MetaInfo{ + ID: im.meta, + State: gen.MetaStateTerminated, + }, } info, err := im.MetaInfo(im.meta) @@ -56,12 +60,11 @@ func (im *meta) HandleMessage(from gen.PID, message any) error { default: im.Log().Error("unable to inspect meta process %s: %s", im.meta, err) // will try next time - im.SendAfter(im.PID(), generate{}, inspectMetaPeriod) + im.SendAfter(im.PID(), generate{id: im.loopID}, inspectMetaPeriod) return nil } - ev.Terminated = false ev.Info = info if err := im.SendEvent(im.event, im.token, ev); err != nil { @@ -69,7 +72,7 @@ func (im *meta) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - im.SendAfter(im.PID(), generate{}, inspectMetaPeriod) + im.SendAfter(im.PID(), generate{id: im.loopID}, inspectMetaPeriod) case requestInspect: response := ResponseInspectMeta{ @@ -107,7 +110,8 @@ func (im *meta) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber im.Log().Debug("got first subscriber. start generating events...") - im.Send(im.PID(), generate{}) + im.loopID++ + im.Send(im.PID(), generate{id: im.loopID}) im.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/meta_state.go b/app/system/inspect/meta_state.go index c27c8e6c2..67f17df9b 100644 --- a/app/system/inspect/meta_state.go +++ b/app/system/inspect/meta_state.go @@ -17,6 +17,7 @@ type meta_state struct { event gen.Atom generating bool + loopID uint64 meta gen.Alias } @@ -32,7 +33,7 @@ func (ims *meta_state) Init(args ...any) error { func (ims *meta_state) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ims.generating == false { + if m.id != ims.loopID || ims.generating == false { ims.Log().Debug("generating canceled") break // cancelled } @@ -44,7 +45,7 @@ func (ims *meta_state) HandleMessage(from gen.PID, message any) error { } ims.Log().Error("unable to inspect meta state %s: %s", ims.meta, err) // will try next time - ims.SendAfter(ims.PID(), generate{}, inspectMetaStatePeriod) + ims.SendAfter(ims.PID(), generate{id: ims.loopID}, inspectMetaStatePeriod) return nil } if state == nil { @@ -62,7 +63,7 @@ func (ims *meta_state) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - ims.SendAfter(ims.PID(), generate{}, inspectMetaStatePeriod) + ims.SendAfter(ims.PID(), generate{id: ims.loopID}, inspectMetaStatePeriod) case requestInspect: response := ResponseInspectMetaState{ @@ -100,7 +101,8 @@ func (ims *meta_state) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ims.Log().Debug("got first subscriber. start generating events...") - ims.Send(ims.PID(), generate{}) + ims.loopID++ + ims.Send(ims.PID(), generate{id: ims.loopID}) ims.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/network.go b/app/system/inspect/network.go index 4a054662d..08839daf5 100644 --- a/app/system/inspect/network.go +++ b/app/system/inspect/network.go @@ -15,6 +15,7 @@ type network struct { token gen.Ref generating bool + loopID uint64 } func (in *network) Init(args ...any) error { @@ -28,7 +29,7 @@ func (in *network) Init(args ...any) error { func (in *network) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if in.generating == false { + if m.id != in.loopID || in.generating == false { in.Log().Debug("generating canceled") break // cancelled } @@ -47,7 +48,7 @@ func (in *network) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - in.SendAfter(in.PID(), generate{}, inspectNetworkPeriod) + in.SendAfter(in.PID(), generate{id: in.loopID}, inspectNetworkPeriod) case requestInspect: info, err := in.Node().Network().Info() @@ -86,7 +87,8 @@ func (in *network) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber in.Log().Debug("got first subscriber. start generating events...") - in.Send(in.PID(), generate{}) + in.loopID++ + in.Send(in.PID(), generate{id: in.loopID}) in.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/node.go b/app/system/inspect/node.go index e7c275fc7..90735875a 100644 --- a/app/system/inspect/node.go +++ b/app/system/inspect/node.go @@ -5,6 +5,7 @@ import ( "fmt" "runtime" "slices" + "time" "ergo.services/ergo/act" "ergo.services/ergo/gen" @@ -19,6 +20,7 @@ type node struct { token gen.Ref generating bool + loopID uint64 } func (in *node) Init(args ...any) error { @@ -32,7 +34,7 @@ func (in *node) Init(args ...any) error { func (in *node) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if in.generating == false { + if m.id != in.loopID || in.generating == false { in.Log().Debug("generating canceled") break // cancelled } @@ -60,7 +62,7 @@ func (in *node) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - in.SendAfter(in.PID(), generate{}, inspectNodePeriod) + in.SendAfter(in.PID(), generate{id: in.loopID}, inspectNodePeriod) case requestInspect: response := ResponseInspectNode{ @@ -72,6 +74,15 @@ func (in *node) HandleMessage(from gen.PID, message any) error { Arch: runtime.GOARCH, OS: runtime.GOOS, Cores: runtime.NumCPU(), + Timezone: func() string { + now := time.Now() + name, _ := now.Zone() + loc := now.Location().String() + if loc == "Local" { + return name // e.g. "MSK", "CET" + } + return loc // e.g. "Europe/Moscow" + }(), Version: in.Node().Version(), Creation: in.Node().Creation(), CRC32: in.Node().Name().CRC32(), @@ -103,14 +114,14 @@ func (in *node) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber in.Log().Debug("got first subscriber. start generating events...") - in.Send(in.PID(), generate{}) + in.loopID++ + in.Send(in.PID(), generate{id: in.loopID}) in.generating = true case gen.MessageEventStop: // no subscribers in.Log().Debug("no subscribers. stop generating") if in.generating { in.generating = false - // wait 10 seconds and terminate this process in.SendAfter(in.PID(), shutdown{}, inspectNodeIdlePeriod) } diff --git a/app/system/inspect/process.go b/app/system/inspect/process.go index 9b94092b8..86efa4f2c 100644 --- a/app/system/inspect/process.go +++ b/app/system/inspect/process.go @@ -18,6 +18,7 @@ type process struct { event gen.Atom pid gen.PID generating bool + loopID uint64 } func (ip *process) Init(args ...any) error { @@ -32,15 +33,18 @@ func (ip *process) Init(args ...any) error { func (ip *process) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ip.generating == false { + if m.id != ip.loopID || ip.generating == false { ip.Log().Debug("generating canceled") break // cancelled } ip.Log().Debug("generating event") ev := MessageInspectProcess{ - Node: ip.Node().Name(), - Terminated: true, + Node: ip.Node().Name(), + Info: gen.ProcessInfo{ + PID: ip.pid, + State: gen.ProcessStateTerminated, + }, } info, err := ip.Node().ProcessInfo(ip.pid) @@ -59,7 +63,7 @@ func (ip *process) HandleMessage(from gen.PID, message any) error { default: ip.Log().Error("unable to inspect process %s: %s", ip.pid, err) // will try next time (seems to be busy) - ip.SendAfter(ip.PID(), generate{}, inspectProcessPeriod) + ip.SendAfter(ip.PID(), generate{id: ip.loopID}, inspectProcessPeriod) return nil } @@ -67,7 +71,6 @@ func (ip *process) HandleMessage(from gen.PID, message any) error { info.Env[k] = fmt.Sprintf("%#v", v) } - ev.Terminated = false ev.Info = info if err := ip.SendEvent(ip.event, ip.token, ev); err != nil { @@ -75,7 +78,7 @@ func (ip *process) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - ip.SendAfter(ip.PID(), generate{}, inspectProcessPeriod) + ip.SendAfter(ip.PID(), generate{id: ip.loopID}, inspectProcessPeriod) case requestInspect: response := ResponseInspectProcess{ @@ -113,7 +116,8 @@ func (ip *process) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ip.Log().Debug("got first subscriber. start generating events...") - ip.Send(ip.PID(), generate{}) + ip.loopID++ + ip.Send(ip.PID(), generate{id: ip.loopID}) ip.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/process_list.go b/app/system/inspect/process_list.go index 9380337bd..7798a5990 100644 --- a/app/system/inspect/process_list.go +++ b/app/system/inspect/process_list.go @@ -16,9 +16,10 @@ type process_list struct { act.Actor token gen.Ref - start int - limit int + start int + limit int generating bool + loopID uint64 event gen.Atom } @@ -34,13 +35,36 @@ func (ipl *process_list) Init(args ...any) error { func (ipl *process_list) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ipl.generating == false { + if m.id != ipl.loopID || ipl.generating == false { ipl.Log().Debug("generating canceled") break // cancelled } ipl.Log().Debug("generating event") - list, err := ipl.Node().ProcessListShortInfo(ipl.start, ipl.limit) + start := ipl.start + if start < 0 { + // negative start means "last N": find the highest PID and work backwards + pids, err := ipl.Node().ProcessList() + if err != nil { + return err + } + if len(pids) > 0 { + // PIDs are not necessarily sorted, find max ID + maxID := uint64(0) + for _, p := range pids { + if p.ID > maxID { + maxID = p.ID + } + } + start = int(maxID) - ipl.limit + if start < 1000 { + start = 1000 + } + } else { + start = 1000 + } + } + list, err := ipl.Node().ProcessListShortInfo(start, ipl.limit) if err != nil { return err } @@ -59,7 +83,7 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - ipl.SendAfter(ipl.PID(), generate{}, inspectProcessListPeriod) + ipl.SendAfter(ipl.PID(), generate{id: ipl.loopID}, inspectProcessListPeriod) case requestInspect: response := ResponseInspectProcessList{ @@ -97,7 +121,8 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ipl.Log().Debug("got first subscriber. start generating events...") - ipl.Send(ipl.PID(), generate{}) + ipl.loopID++ + ipl.Send(ipl.PID(), generate{id: ipl.loopID}) ipl.generating = true case gen.MessageEventStop: // no subscribers diff --git a/app/system/inspect/process_range.go b/app/system/inspect/process_range.go new file mode 100644 index 000000000..869446971 --- /dev/null +++ b/app/system/inspect/process_range.go @@ -0,0 +1,191 @@ +package inspect + +import ( + "fmt" + "slices" + "strings" + + "ergo.services/ergo/act" + "ergo.services/ergo/gen" +) + +func factory_process_range() gen.ProcessBehavior { + return &process_range{} +} + +type process_range struct { + act.Actor + token gen.Ref + + name string + behavior string + application string + state string + minMailbox uint64 + limit int + hash string + + generating bool + loopID uint64 + event gen.Atom +} + +func (ipr *process_range) Init(args ...any) error { + ipr.name = args[0].(string) + ipr.behavior = args[1].(string) + ipr.application = args[2].(string) + ipr.state = args[3].(string) + ipr.minMailbox = args[4].(uint64) + ipr.limit = args[5].(int) + ipr.hash = args[6].(string) + + ipr.Log().SetLogger("default") + ipr.Log().Debug("process range inspector started. name=%q behavior=%q app=%q state=%q mailbox>=%d limit=%d", + ipr.name, ipr.behavior, ipr.application, ipr.state, ipr.minMailbox, ipr.limit) + ipr.Send(ipr.PID(), register{}) + return nil +} + +func (ipr *process_range) HandleMessage(from gen.PID, message any) error { + switch m := message.(type) { + case generate: + if m.id != ipr.loopID || ipr.generating == false { + break + } + + var list []gen.ProcessShortInfo + nameLower := strings.ToLower(ipr.name) + behaviorLower := strings.ToLower(ipr.behavior) + appLower := strings.ToLower(ipr.application) + + ipr.Node().ProcessRangeShortInfo(func(info gen.ProcessShortInfo) bool { + // apply filters + if nameLower != "" { + if strings.Contains(strings.ToLower(string(info.Name)), nameLower) == false { + return true // skip, continue + } + } + if behaviorLower != "" { + if strings.Contains(strings.ToLower(info.Behavior), behaviorLower) == false { + return true + } + } + if appLower != "" { + if strings.Contains(strings.ToLower(string(info.Application)), appLower) == false { + return true + } + } + if ipr.state != "" { + if strings.EqualFold(info.State.String(), ipr.state) == false { + return true + } + } + if ipr.minMailbox > 0 { + if info.MessagesMailbox < ipr.minMailbox { + return true + } + } + + list = append(list, info) + + if ipr.limit > 0 && len(list) >= ipr.limit { + return false // stop iteration + } + return true + }) + + slices.SortStableFunc(list, func(a, b gen.ProcessShortInfo) int { + return int(a.PID.ID - b.PID.ID) + }) + + // reuse MessageInspectProcessList — same payload format + ev := MessageInspectProcessList{ + Node: ipr.Node().Name(), + Processes: list, + } + + if err := ipr.SendEvent(ipr.event, ipr.token, ev); err != nil { + ipr.Log().Error("unable to send event %q: %s", ipr.event, err) + return gen.TerminateReasonNormal + } + + ipr.SendAfter(ipr.PID(), generate{id: ipr.loopID}, inspectProcessRangePeriod) + + case requestInspect: + response := ResponseInspectProcessRange{ + Event: gen.Event{ + Name: ipr.event, + Node: ipr.Node().Name(), + }, + } + ipr.SendResponse(m.pid, m.ref, response) + + case register: + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + ipr.event = gen.Atom(fmt.Sprintf("%s_%s", inspectProcessRange, ipr.hash)) + token, err := ipr.RegisterEvent(ipr.event, eopts) + if err != nil { + ipr.Log().Error("unable to register event: %s", err) + return err + } + ipr.Log().Info("registered event %s", ipr.event) + ipr.token = token + ipr.SendAfter(ipr.PID(), shutdown{}, inspectProcessRangeIdlePeriod) + + case shutdown: + if ipr.generating { + break + } + return gen.TerminateReasonNormal + + case gen.MessageEventStart: + ipr.Log().Debug("got first subscriber. start generating events...") + ipr.loopID++ + ipr.Send(ipr.PID(), generate{id: ipr.loopID}) + ipr.generating = true + + case gen.MessageEventStop: + ipr.Log().Debug("no subscribers. stop generating") + if ipr.generating { + ipr.generating = false + ipr.SendAfter(ipr.PID(), shutdown{}, inspectProcessRangeIdlePeriod) + } + + default: + ipr.Log().Error("unknown message (ignored) %#v", message) + } + + return nil +} + +func (ipr *process_range) Terminate(reason error) { + ipr.Log().Debug("process range inspector terminated: %s", reason) +} + +// filterHash builds a short deterministic suffix from filter fields +func filterHash(name, behavior, application, state string, minMailbox uint64, limit int) string { + return fmt.Sprintf("%x", hashStr(fmt.Sprintf("%s|%s|%s|%s|%d|%d", + name, behavior, application, state, minMailbox, limit))) +} + +// eventListHash builds a short deterministic suffix from event list filter fields +func eventListHash(name string, notify, buffered int, minSubscribers int64, limit int) string { + return fmt.Sprintf("%x", hashStr(fmt.Sprintf("%s|%d|%d|%d|%d", + name, notify, buffered, minSubscribers, limit))) +} + +func connectionListHash(name string, limit int) string { + return fmt.Sprintf("%x", hashStr(fmt.Sprintf("%s|%d", name, limit))) +} + +func hashStr(s string) uint32 { + h := uint32(2166136261) + for i := 0; i < len(s); i++ { + h ^= uint32(s[i]) + h *= 16777619 + } + return h +} diff --git a/app/system/inspect/process_state.go b/app/system/inspect/process_state.go index 4c3badad9..8bdb1c40d 100644 --- a/app/system/inspect/process_state.go +++ b/app/system/inspect/process_state.go @@ -17,6 +17,7 @@ type process_state struct { event gen.Atom generating bool + loopID uint64 pid gen.PID } @@ -32,7 +33,7 @@ func (ips *process_state) Init(args ...any) error { func (ips *process_state) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: - if ips.generating == false { + if m.id != ips.loopID || ips.generating == false { ips.Log().Debug("generating canceled") break // cancelled } @@ -44,7 +45,7 @@ func (ips *process_state) HandleMessage(from gen.PID, message any) error { } ips.Log().Error("unable to inspect process state %s: %s", ips.pid, err) // will try next time - ips.SendAfter(ips.PID(), generate{}, inspectProcessStatePeriod) + ips.SendAfter(ips.PID(), generate{id: ips.loopID}, inspectProcessStatePeriod) return nil } @@ -59,7 +60,7 @@ func (ips *process_state) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - ips.SendAfter(ips.PID(), generate{}, inspectProcessStatePeriod) + ips.SendAfter(ips.PID(), generate{id: ips.loopID}, inspectProcessStatePeriod) case requestInspect: response := ResponseInspectProcessState{ @@ -97,7 +98,8 @@ func (ips *process_state) HandleMessage(from gen.PID, message any) error { case gen.MessageEventStart: // got first subscriber ips.Log().Debug("got first subscriber. start generating events...") - ips.Send(ips.PID(), generate{}) + ips.loopID++ + ips.Send(ips.PID(), generate{id: ips.loopID}) ips.generating = true case gen.MessageEventStop: // no subscribers diff --git a/docs/basics/logging.md b/docs/basics/logging.md index fd0355c64..bbdf853cc 100644 --- a/docs/basics/logging.md +++ b/docs/basics/logging.md @@ -282,10 +282,10 @@ Different processes often need different verbosity. Most processes log at Info. ```go // Debugging a specific process -node.SetLogLevelProcess(suspiciousPID, gen.LogLevelDebug) +node.SetProcessLogLevel(suspiciousPID, gen.LogLevelDebug) // Later, restore normal level -node.SetLogLevelProcess(suspiciousPID, gen.LogLevelInfo) +node.SetProcessLogLevel(suspiciousPID, gen.LogLevelInfo) ``` For processes generating high-volume logs, route them to a dedicated logger using a hidden logger. A trading engine logging every order would overwhelm general logs: diff --git a/gen/network.go b/gen/network.go index 40b498878..6feb80066 100644 --- a/gen/network.go +++ b/gen/network.go @@ -539,6 +539,9 @@ type RemoteNodeInfo struct { // Reported during handshake. Messages exceeding this are rejected. MaxMessageSize int + // TLS indicates whether this connection uses TLS encryption. + TLS bool + // MessagesIn is the total number of messages received from this remote node. MessagesIn uint64 diff --git a/gen/node.go b/gen/node.go index dbfba85f6..121b7b13e 100644 --- a/gen/node.go +++ b/gen/node.go @@ -397,25 +397,47 @@ type Node interface { // Available in all states. Log() Log - // LogLevelProcess returns the logging level for the given process. + // SetProcessLogLevel sets the logging level for the given process. // Available in: Running state only. // Returns ErrNodeTerminated in other states. - LogLevelProcess(pid PID) (LogLevel, error) + SetProcessLogLevel(pid PID, level LogLevel) error - // SetLogLevelProcess sets the logging level for the given process. + // SetProcessSendPriority sets the default message sending priority for the given process. // Available in: Running state only. - // Returns ErrNodeTerminated in other states. - SetLogLevelProcess(pid PID, level LogLevel) error + SetProcessSendPriority(pid PID, priority MessagePriority) error - // LogLevelMeta returns the logging level for the given meta process. + // SetProcessCompression enables or disables compression for the given process. // Available in: Running state only. - // Returns ErrNodeTerminated in other states. - LogLevelMeta(meta Alias) (LogLevel, error) + SetProcessCompression(pid PID, enabled bool) error + + // SetProcessCompressionType sets the compression type for the given process. + // Available in: Running state only. + SetProcessCompressionType(pid PID, ctype CompressionType) error + + // SetProcessCompressionLevel sets the compression level for the given process. + // Available in: Running state only. + SetProcessCompressionLevel(pid PID, level CompressionLevel) error + + // SetProcessCompressionThreshold sets the minimum message size that triggers compression for the given process. + // Available in: Running state only. + SetProcessCompressionThreshold(pid PID, threshold int) error + + // SetProcessKeepNetworkOrder enables or disables maintaining delivery order over the network for the given process. + // Available in: Running state only. + SetProcessKeepNetworkOrder(pid PID, order bool) error - // SetLogLevelMeta sets the logging level for the given meta process. + // SetProcessImportantDelivery enables or disables the important delivery flag for the given process. + // Available in: Running state only. + SetProcessImportantDelivery(pid PID, important bool) error + + // SetMetaLogLevel sets the logging level for the given meta process. // Available in: Running state only. // Returns ErrNodeTerminated in other states. - SetLogLevelMeta(meta Alias, level LogLevel) error + SetMetaLogLevel(meta Alias, level LogLevel) error + + // SetMetaSendPriority sets the default message sending priority for the given meta process. + // Available in: Running state only. + SetMetaSendPriority(meta Alias, priority MessagePriority) error // Loggers returns a list of registered logger names. // Available in all states. diff --git a/net/edf/init.go b/net/edf/init.go index 2836c8c40..29486d30f 100644 --- a/net/edf/init.go +++ b/net/edf/init.go @@ -44,6 +44,8 @@ var ( gen.ApplicationOptionsExtra{}, gen.ApplicationInfo{}, gen.MetaInfo{}, + gen.EventInfo{}, + gen.LogField{}, gen.NetworkFlags{}, gen.NetworkProxyFlags{}, @@ -81,12 +83,17 @@ var ( inspect.ResponseInspectProcessList{}, inspect.MessageInspectProcessList{}, + inspect.RequestInspectProcessRange{}, + inspect.ResponseInspectProcessRange{}, + + inspect.RequestInspectEventList{}, + inspect.ResponseInspectEventList{}, + inspect.MessageInspectEventList{}, + inspect.RequestInspectLog{}, inspect.ResponseInspectLog{}, - inspect.MessageInspectLogNode{}, - inspect.MessageInspectLogNetwork{}, - inspect.MessageInspectLogProcess{}, - inspect.MessageInspectLogMeta{}, + inspect.InspectLogEntry{}, + inspect.MessageInspectLog{}, inspect.RequestInspectProcess{}, inspect.ResponseInspectProcess{}, @@ -120,10 +127,34 @@ var ( inspect.ResponseDoKill{}, inspect.RequestDoSetLogLevel{}, - inspect.RequestDoSetLogLevelProcess{}, - inspect.RequestDoSetLogLevelMeta{}, + inspect.RequestDoSetProcessLogLevel{}, + inspect.RequestDoSetMetaLogLevel{}, inspect.ResponseDoSetLogLevel{}, + inspect.RequestDoSetProcessSendPriority{}, + inspect.RequestDoSetProcessCompression{}, + inspect.RequestDoSetProcessCompressionType{}, + inspect.RequestDoSetProcessCompressionLevel{}, + inspect.RequestDoSetProcessCompressionThreshold{}, + inspect.RequestDoSetProcessKeepNetworkOrder{}, + inspect.RequestDoSetProcessImportantDelivery{}, + inspect.RequestDoSetMetaSendPriority{}, + inspect.ResponseDoSet{}, + + inspect.RequestDoAppStart{}, + inspect.ResponseDoAppStart{}, + inspect.RequestDoAppStop{}, + inspect.ResponseDoAppStop{}, + inspect.RequestDoAppUnload{}, + inspect.ResponseDoAppUnload{}, + + inspect.RequestDoInspect{}, + inspect.ResponseDoInspect{}, + + inspect.RequestInspectConnectionList{}, + inspect.ResponseInspectConnectionList{}, + inspect.MessageInspectConnectionList{}, + inspect.RequestInspectApplicationList{}, inspect.ResponseInspectApplicationList{}, inspect.MessageInspectApplicationList{}, diff --git a/net/handshake/accept.go b/net/handshake/accept.go index fec394a4f..c3f146a76 100644 --- a/net/handshake/accept.go +++ b/net/handshake/accept.go @@ -175,8 +175,10 @@ func (h *handshake) Accept(node gen.NodeHandshake, conn net.Conn, options gen.Ha result.PoolDSN = accept.PoolDSN result.Tail = tail + _, isTLS := conn.(*tls.Conn) custom := ConnectionOptions{ PoolSize: h.poolsize, + TLS: isTLS, EncodeAtomCache: h.makeEncodeAtomCache(intro2.AtomCache), EncodeRegCache: h.makeEncodeRegCache(intro2.RegCache), EncodeErrCache: h.makeEncodeErrCache(intro2.ErrCache), diff --git a/net/handshake/start.go b/net/handshake/start.go index 65ef37233..2d717cdb2 100644 --- a/net/handshake/start.go +++ b/net/handshake/start.go @@ -131,9 +131,11 @@ func (h *handshake) Start(node gen.NodeHandshake, conn net.Conn, options gen.Han result.PoolDSN = accept.PoolDSN result.Tail = tail + _, isTLS := conn.(*tls.Conn) custom := ConnectionOptions{ PoolSize: accept.PoolSize, PoolDSN: accept.PoolDSN, + TLS: isTLS, EncodeAtomCache: h.makeEncodeAtomCache(intro.AtomCache), EncodeRegCache: h.makeEncodeRegCache(intro.RegCache), EncodeErrCache: h.makeEncodeErrCache(intro.ErrCache), diff --git a/net/handshake/types.go b/net/handshake/types.go index 10a647ebb..f19bc05c2 100644 --- a/net/handshake/types.go +++ b/net/handshake/types.go @@ -63,6 +63,7 @@ type MessageReject struct { type ConnectionOptions struct { PoolSize int PoolDSN []string + TLS bool EncodeAtomCache *sync.Map EncodeRegCache *sync.Map diff --git a/net/proto/connection.go b/net/proto/connection.go index de6f47bba..a65e0b7b3 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -44,6 +44,7 @@ type connection struct { pool_dsn []string pool_size int + tls bool pool_mutex sync.RWMutex pool []*pool_item @@ -158,6 +159,7 @@ func (c *connection) Info() gen.RemoteNodeInfo { PoolDSN: c.pool_dsn, MaxMessageSize: c.peer_maxmessagesize, + TLS: c.tls, MessagesIn: atomic.LoadUint64(&c.messagesIn), MessagesOut: atomic.LoadUint64(&c.messagesOut), diff --git a/net/proto/enp.go b/net/proto/enp.go index e34fd394c..b36dee969 100644 --- a/net/proto/enp.go +++ b/net/proto/enp.go @@ -53,6 +53,7 @@ func (e *enp) NewConnection(core gen.Core, result gen.HandshakeResult, log gen.L pool_size: opts.PoolSize, pool_dsn: opts.PoolDSN, + tls: opts.TLS, encodeOptions: edf.Options{ AtomCache: opts.EncodeAtomCache, diff --git a/node/application.go b/node/application.go index 40b241d58..58e6012bd 100644 --- a/node/application.go +++ b/node/application.go @@ -60,10 +60,7 @@ func (a *application) start(mode gen.ApplicationMode, options gen.ApplicationOpt deadline := time.Now().Unix() + int64(timeout) ref, err := a.node.MakeRefWithDeadline(deadline) if err != nil { - a.group.Range(func(pid gen.PID, _ bool) bool { - a.node.Kill(pid) - return true - }) + a.killMembers() atomic.StoreInt32(&a.state, int32(gen.ApplicationStateLoaded)) return err } @@ -83,10 +80,7 @@ func (a *application) start(mode gen.ApplicationMode, options gen.ApplicationOpt pid, err := a.node.spawn(item.Factory, opts) if err != nil { - a.group.Range(func(pid gen.PID, _ bool) bool { - a.node.Kill(pid) - return true - }) + a.killMembers() atomic.StoreInt32(&a.state, int32(gen.ApplicationStateLoaded)) return err } @@ -140,14 +134,14 @@ func (a *application) stop(force bool, timeout time.Duration) error { // update mode to prevent triggering 'permantent' mode a.mode = gen.ApplicationModeTemporary - a.group.Range(func(pid gen.PID, _ bool) bool { + pids := a.collectMemberPIDs() + for _, pid := range pids { if force { a.node.Kill(pid) } else { a.node.SendExit(pid, gen.TerminateReasonShutdown) } - return true - }) + } if force { a.reason = gen.TerminateReasonKill @@ -180,10 +174,7 @@ func (a *application) terminate(pid gen.PID, reason error) { a.node.Log(). Info("application %s (%s) will be stopped due to termination of %s with reason: %s", a.spec.Name, a.mode, pid, reason) a.reason = reason - a.group.Range(func(pid gen.PID, _ bool) bool { - a.node.SendExit(pid, gen.TerminateReasonShutdown) - return true - }) + a.exitMembers(gen.TerminateReasonShutdown) case gen.ApplicationModeTransient: if reason == gen.TerminateReasonNormal || reason == gen.TerminateReasonShutdown { // do nothing @@ -198,10 +189,7 @@ func (a *application) terminate(pid gen.PID, reason error) { break } a.reason = reason - a.group.Range(func(pid gen.PID, _ bool) bool { - a.node.SendExit(pid, gen.TerminateReasonShutdown) - return true - }) + a.exitMembers(gen.TerminateReasonShutdown) default: // do nothing } @@ -297,6 +285,27 @@ func (a *application) isRunning() bool { return atomic.LoadInt32(&a.state) == int32(gen.ApplicationStateRunning) } +func (a *application) collectMemberPIDs() []gen.PID { + var pids []gen.PID + a.group.Range(func(pid gen.PID, _ bool) bool { + pids = append(pids, pid) + return true + }) + return pids +} + +func (a *application) killMembers() { + for _, pid := range a.collectMemberPIDs() { + a.node.Kill(pid) + } +} + +func (a *application) exitMembers(reason error) { + for _, pid := range a.collectMemberPIDs() { + a.node.SendExit(pid, reason) + } +} + func (a *application) registerAppRoute() { appRoute := gen.ApplicationRoute{ Node: a.node.name, diff --git a/node/node.go b/node/node.go index 08bc8457e..a1d8bc13b 100644 --- a/node/node.go +++ b/node/node.go @@ -588,7 +588,7 @@ func (n *node) ProcessInfo(pid gen.PID) (gen.ProcessInfo, error) { return info, nil } -func (n *node) SetLogLevelProcess(pid gen.PID, level gen.LogLevel) error { +func (n *node) SetProcessLogLevel(pid gen.PID, level gen.LogLevel) error { if n.isRunning() == false { return gen.ErrNodeTerminated } @@ -601,22 +601,123 @@ func (n *node) SetLogLevelProcess(pid gen.PID, level gen.LogLevel) error { return p.log.SetLevel(level) } -func (n *node) LogLevelProcess(pid gen.PID) (gen.LogLevel, error) { - var level gen.LogLevel + +func (n *node) SetProcessSendPriority(pid gen.PID, priority gen.MessagePriority) error { if n.isRunning() == false { - return level, gen.ErrNodeTerminated + return gen.ErrNodeTerminated + } + switch priority { + case gen.MessagePriorityNormal: + case gen.MessagePriorityHigh: + case gen.MessagePriorityMax: + default: + return gen.ErrIncorrect } value, loaded := n.processes.Load(pid) if loaded == false { - return level, gen.ErrProcessUnknown + return gen.ErrProcessUnknown } + p := value.(*process) + p.priority = priority + return nil +} +func (n *node) SetProcessCompression(pid gen.PID, enabled bool) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } + p := value.(*process) + p.compression.Enable = enabled + return nil +} + +func (n *node) SetProcessCompressionType(pid gen.PID, ctype gen.CompressionType) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + switch ctype { + case gen.CompressionTypeGZIP: + case gen.CompressionTypeLZW: + case gen.CompressionTypeZLIB: + default: + return gen.ErrIncorrect + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } p := value.(*process) - level = p.log.Level() - return level, nil + p.compression.Type = ctype + return nil } -func (n *node) SetLogLevelMeta(m gen.Alias, level gen.LogLevel) error { +func (n *node) SetProcessCompressionLevel(pid gen.PID, level gen.CompressionLevel) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + switch level { + case gen.CompressionBestSize: + case gen.CompressionBestSpeed: + case gen.CompressionDefault: + default: + return gen.ErrIncorrect + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } + p := value.(*process) + p.compression.Level = level + return nil +} + +func (n *node) SetProcessCompressionThreshold(pid gen.PID, threshold int) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + if threshold < gen.DefaultCompressionThreshold { + return gen.ErrIncorrect + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } + p := value.(*process) + p.compression.Threshold = threshold + return nil +} + +func (n *node) SetProcessKeepNetworkOrder(pid gen.PID, order bool) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } + p := value.(*process) + p.keeporder = order + return nil +} + +func (n *node) SetProcessImportantDelivery(pid gen.PID, important bool) error { + if n.isRunning() == false { + return gen.ErrNodeTerminated + } + value, loaded := n.processes.Load(pid) + if loaded == false { + return gen.ErrProcessUnknown + } + p := value.(*process) + p.important = important + return nil +} + +func (n *node) SetMetaLogLevel(m gen.Alias, level gen.LogLevel) error { if n.isRunning() == false { return gen.ErrNodeTerminated } @@ -636,26 +737,32 @@ func (n *node) SetLogLevelMeta(m gen.Alias, level gen.LogLevel) error { return mp.log.SetLevel(level) } -func (n *node) LogLevelMeta(m gen.Alias) (gen.LogLevel, error) { - var level gen.LogLevel +func (n *node) SetMetaSendPriority(m gen.Alias, priority gen.MessagePriority) error { if n.isRunning() == false { - return level, gen.ErrNodeTerminated + return gen.ErrNodeTerminated } value, loaded := n.aliases.Load(m) if loaded == false { - return level, gen.ErrProcessUnknown + return gen.ErrProcessUnknown } p := value.(*process) value, loaded = p.metas.Load(m) if loaded == false { - return level, gen.ErrMetaUnknown + return gen.ErrMetaUnknown } mp := value.(*meta) - level = mp.log.Level() - return level, nil + switch priority { + case gen.MessagePriorityNormal: + case gen.MessagePriorityHigh: + case gen.MessagePriorityMax: + default: + return gen.ErrIncorrect + } + mp.priority = priority + return nil } func (n *node) Info() (gen.NodeInfo, error) { diff --git a/testing/unit/node.go b/testing/unit/node.go index 96c3c77df..127409177 100644 --- a/testing/unit/node.go +++ b/testing/unit/node.go @@ -634,19 +634,43 @@ func (tn *TestNode) Log() gen.Log { return tn.log } -func (tn *TestNode) LogLevelProcess(pid gen.PID) (gen.LogLevel, error) { - return gen.LogLevelInfo, nil +func (tn *TestNode) SetProcessLogLevel(pid gen.PID, level gen.LogLevel) error { + return nil +} + +func (tn *TestNode) SetProcessSendPriority(pid gen.PID, priority gen.MessagePriority) error { + return nil +} + +func (tn *TestNode) SetProcessCompression(pid gen.PID, enabled bool) error { + return nil +} + +func (tn *TestNode) SetProcessCompressionType(pid gen.PID, ctype gen.CompressionType) error { + return nil } -func (tn *TestNode) SetLogLevelProcess(pid gen.PID, level gen.LogLevel) error { +func (tn *TestNode) SetProcessCompressionLevel(pid gen.PID, level gen.CompressionLevel) error { return nil } -func (tn *TestNode) LogLevelMeta(meta gen.Alias) (gen.LogLevel, error) { - return gen.LogLevelInfo, nil +func (tn *TestNode) SetProcessCompressionThreshold(pid gen.PID, threshold int) error { + return nil +} + +func (tn *TestNode) SetProcessKeepNetworkOrder(pid gen.PID, order bool) error { + return nil +} + +func (tn *TestNode) SetProcessImportantDelivery(pid gen.PID, important bool) error { + return nil +} + +func (tn *TestNode) SetMetaLogLevel(meta gen.Alias, level gen.LogLevel) error { + return nil } -func (tn *TestNode) SetLogLevelMeta(meta gen.Alias, level gen.LogLevel) error { +func (tn *TestNode) SetMetaSendPriority(meta gen.Alias, priority gen.MessagePriority) error { return nil } From d6ca1bb8a8f7191b10390aaf6e9ebef9c804a961 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 17 Mar 2026 11:52:34 +0100 Subject: [PATCH 050/122] sync --- app/system/inspect/inspect.go | 9 +++-- app/system/inspect/log.go | 65 ++++++++++++++++++++++++++--------- app/system/inspect/message.go | 6 ++-- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/app/system/inspect/inspect.go b/app/system/inspect/inspect.go index ea3d29968..bb2b8180b 100644 --- a/app/system/inspect/inspect.go +++ b/app/system/inspect/inspect.go @@ -307,8 +307,13 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error levels = inspectLogFilter } - pname := gen.Atom(fmt.Sprintf("%s_%s", inspectLog, name)) - _, err := i.SpawnRegister(pname, factory_log, opts, levels) + limit := r.Limit + if limit < 1 { + limit = 500 + } + + pname := gen.Atom(fmt.Sprintf("%s_%s_%d", inspectLog, name, limit)) + _, err := i.SpawnRegister(pname, factory_log, opts, levels, limit) if err != nil && err != gen.ErrTaken { return err, nil } diff --git a/app/system/inspect/log.go b/app/system/inspect/log.go index b41377f4c..76157112d 100644 --- a/app/system/inspect/log.go +++ b/app/system/inspect/log.go @@ -18,18 +18,25 @@ type log struct { event gen.Atom levels []gen.LogLevel + limit int generating bool loopID uint64 - buffer []InspectLogEntry + + // ring buffer + ring []InspectLogEntry + pos int + full bool + received int64 } const logFlushInterval = time.Second func (il *log) Init(args ...any) error { il.levels = args[0].([]gen.LogLevel) + il.limit = args[1].(int) + il.ring = make([]InspectLogEntry, il.limit) il.Log().SetLogger("default") - il.Log().Debug("log inspector started") - // RegisterEvent is not allowed here + il.Log().Debug("log inspector started (limit: %d)", il.limit) il.Send(il.PID(), register{}) return nil } @@ -43,16 +50,38 @@ func (il *log) HandleMessage(from gen.PID, message any) error { if m.id != il.loopID || il.generating == false { break } - if len(il.buffer) == 0 { + if il.received == 0 { il.SendAfter(il.PID(), flushLog{id: il.loopID}, logFlushInterval) break } + // collect entries from ring buffer in correct order + var entries []InspectLogEntry + if il.full { + // ring wrapped: oldest at pos, newest at pos-1 + entries = make([]InspectLogEntry, il.limit) + copy(entries, il.ring[il.pos:]) + copy(entries[il.limit-il.pos:], il.ring[:il.pos]) + } else { + entries = make([]InspectLogEntry, il.pos) + copy(entries, il.ring[:il.pos]) + } + + suppressed := il.received - int64(len(entries)) + if suppressed < 0 { + suppressed = 0 + } + ev := MessageInspectLog{ - Node: il.Node().Name(), - Entries: il.buffer, + Node: il.Node().Name(), + Entries: entries, + Suppressed: suppressed, } - il.buffer = nil + + // reset ring + il.pos = 0 + il.full = false + il.received = 0 if err := il.SendEvent(il.event, il.token, ev); err != nil { return gen.TerminateReasonNormal @@ -85,26 +114,24 @@ func (il *log) HandleMessage(from gen.PID, message any) error { case shutdown: if il.generating { - break // ignore. + break // ignore } return gen.TerminateReasonNormal case gen.MessageEventStart: // got first subscriber - // register this process as a logger il.Log().Debug("add this process as a logger") il.Node().LoggerAddPID(il.PID(), il.PID().String(), il.levels...) - // we cant use Log() method while this process registered as a logger il.loopID++ il.generating = true il.SendAfter(il.PID(), flushLog{id: il.loopID}, logFlushInterval) case gen.MessageEventStop: // no subscribers - // unregister this process as a logger il.Node().LoggerDeletePID(il.PID()) - // now we can use Log() method il.Log().Debug("removed this process as a logger") il.generating = false - il.buffer = nil + il.pos = 0 + il.full = false + il.received = 0 il.SendAfter(il.PID(), shutdown{}, inspectLogIdlePeriod) } @@ -138,13 +165,17 @@ func (il *log) HandleLog(message gen.MessageLog) error { entry.Peer = gen.Atom(m.Peer.CRC32()) } - il.buffer = append(il.buffer, entry) + il.ring[il.pos] = entry + il.pos++ + if il.pos >= il.limit { + il.pos = 0 + il.full = true + } + il.received++ + return nil } func (il *log) Terminate(reason error) { - // since this process is already unregistered - // it is also unregistered as a logger - // so we can use Log() here il.Log().Debug("log inspector terminated: %s", reason) } diff --git a/app/system/inspect/message.go b/app/system/inspect/message.go index 78da25898..cc7f8e895 100644 --- a/app/system/inspect/message.go +++ b/app/system/inspect/message.go @@ -83,6 +83,7 @@ type MessageInspectProcessList struct { type RequestInspectLog struct { Levels []gen.LogLevel + Limit int } type ResponseInspectLog struct { Event gen.Event @@ -104,8 +105,9 @@ type InspectLogEntry struct { } type MessageInspectLog struct { - Node gen.Atom - Entries []InspectLogEntry + Node gen.Atom + Entries []InspectLogEntry + Suppressed int64 } // process From 0565f71eb2e9b2b97d00b308cceb30694f22872b Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Tue, 17 Mar 2026 14:26:42 +0100 Subject: [PATCH 051/122] opt tm --- node/tm/event.go | 43 +++++++++++++++++++++------------------ node/tm/event_test.go | 21 ++++++++++--------- node/tm/manager.go | 37 ++++++++++++++++++++++++++++++--- node/tm/query.go | 20 +++++++++--------- node/tm/scenarios_test.go | 2 +- 5 files changed, 79 insertions(+), 44 deletions(-) diff --git a/node/tm/event.go b/node/tm/event.go index 410fa8499..0a67a409d 100644 --- a/node/tm/event.go +++ b/node/tm/event.go @@ -34,10 +34,12 @@ func (tm *targetManager) RegisterEvent(producer gen.PID, name gen.Atom, options subscriberCount: 0, } - // Create buffer if configured + // Create ring buffer if configured if options.Buffer > 0 { - entry.buffer = make([]gen.MessageEvent, 0, options.Buffer) - entry.bufferSize = options.Buffer + entry.buffer = &eventRingBuffer{ + data: make([]gen.MessageEvent, options.Buffer), + size: options.Buffer, + } } tm.events[event] = entry @@ -182,7 +184,7 @@ func (tm *targetManager) publishEventLocalProducer( return gen.ErrEventOwner } - // Store in buffer if configured (needs write lock) + // Store in ring buffer if configured (needs write lock) if entry.buffer != nil { // Re-check after lock upgrade entry, exists = tm.events[message.Event] @@ -190,12 +192,7 @@ func (tm *targetManager) publishEventLocalProducer( tm.mutex.Unlock() return gen.ErrEventOwner } - if len(entry.buffer) < entry.bufferSize { - entry.buffer = append(entry.buffer, message) - } else { - copy(entry.buffer, entry.buffer[1:]) - entry.buffer[entry.bufferSize-1] = message - } + entry.buffer.push(message) } // Increment per-event published counter under lock @@ -759,11 +756,16 @@ func (tm *targetManager) EventInfo(event gen.Event) (gen.EventInfo, error) { } // Build event info + var bufSize, bufLen int + if entry.buffer != nil { + bufSize = entry.buffer.size + bufLen = entry.buffer.len + } info := gen.EventInfo{ Event: event, Producer: entry.producer, - BufferSize: entry.bufferSize, - CurrentBuffer: len(entry.buffer), + BufferSize: bufSize, + CurrentBuffer: bufLen, Notify: entry.notify, Subscribers: entry.subscriberCount, MessagesPublished: entry.messagesPublished.Load(), @@ -780,11 +782,16 @@ func (tm *targetManager) EventRangeInfo(fn func(gen.EventInfo) bool) error { // Snapshot event infos under lock infos := make([]gen.EventInfo, 0, len(tm.events)) for event, entry := range tm.events { + var bufSize, bufLen int + if entry.buffer != nil { + bufSize = entry.buffer.size + bufLen = entry.buffer.len + } info := gen.EventInfo{ Event: event, Producer: entry.producer, - BufferSize: entry.bufferSize, - CurrentBuffer: len(entry.buffer), + BufferSize: bufSize, + CurrentBuffer: bufLen, Notify: entry.notify, Subscribers: entry.subscriberCount, MessagesPublished: entry.messagesPublished.Load(), @@ -805,14 +812,10 @@ func (tm *targetManager) EventRangeInfo(fn func(gen.EventInfo) bool) error { return nil } -// Helper: get event buffer +// Helper: get event buffer snapshot func (tm *targetManager) getEventBuffer(entry *eventEntry) []gen.MessageEvent { if entry.buffer == nil { return nil } - - // Return copy of buffer - buffer := make([]gen.MessageEvent, len(entry.buffer)) - copy(buffer, entry.buffer) - return buffer + return entry.buffer.snapshot() } diff --git a/node/tm/event_test.go b/node/tm/event_test.go index 1937ae27c..b1032de7d 100644 --- a/node/tm/event_test.go +++ b/node/tm/event_test.go @@ -35,8 +35,8 @@ func TestRegisterEvent_Basic(t *testing.T) { t.Error("Producer should match") } - if entry.bufferSize != 10 { - t.Errorf("Buffer size should be 10, got %d", entry.bufferSize) + if entry.buffer == nil || entry.buffer.size != 10 { + t.Errorf("Buffer size should be 10") } if entry.notify == false { @@ -389,8 +389,8 @@ func TestPublishEvent_UpdatesBuffer(t *testing.T) { // Check buffer entry := tm.events[event] - if len(entry.buffer) != 3 { - t.Errorf("Buffer should have 3 messages, got %d", len(entry.buffer)) + if entry.buffer.len != 3 { + t.Errorf("Buffer should have 3 messages, got %d", entry.buffer.len) } } @@ -427,16 +427,17 @@ func TestPublishEvent_BufferOverflow(t *testing.T) { // Buffer should have 2 messages (msg2, msg3 - msg1 flushed) entry := tm.events[event] - if len(entry.buffer) != 2 { - t.Errorf("Buffer should have 2 messages, got %d", len(entry.buffer)) + if entry.buffer.len != 2 { + t.Errorf("Buffer should have 2 messages, got %d", entry.buffer.len) } - // msg2 and msg3 should be in buffer - if len(entry.buffer) >= 2 { - if entry.buffer[0].Message != "msg2" { + // msg2 and msg3 should be in buffer (oldest first) + snap := entry.buffer.snapshot() + if len(snap) >= 2 { + if snap[0].Message != "msg2" { t.Error("First message should be msg2 (msg1 flushed)") } - if entry.buffer[1].Message != "msg3" { + if snap[1].Message != "msg3" { t.Error("Second message should be msg3") } } diff --git a/node/tm/manager.go b/node/tm/manager.go index ae6a57cd1..c3679d770 100644 --- a/node/tm/manager.go +++ b/node/tm/manager.go @@ -43,14 +43,45 @@ type targetEntry struct { consumers map[gen.PID]struct{} } +// eventRingBuffer is a fixed-size circular buffer for event messages. +// O(1) push, O(n) snapshot. No copy-shift on overflow. +type eventRingBuffer struct { + data []gen.MessageEvent + size int // capacity + head int // index of oldest element + len int // current number of elements +} + +func (rb *eventRingBuffer) push(msg gen.MessageEvent) { + idx := (rb.head + rb.len) % rb.size + if rb.len < rb.size { + rb.data[idx] = msg + rb.len++ + } else { + // overwrite oldest + rb.data[rb.head] = msg + rb.head = (rb.head + 1) % rb.size + } +} + +func (rb *eventRingBuffer) snapshot() []gen.MessageEvent { + if rb.len == 0 { + return make([]gen.MessageEvent, 0) + } + result := make([]gen.MessageEvent, rb.len) + for i := 0; i < rb.len; i++ { + result[i] = rb.data[(rb.head+i)%rb.size] + } + return result +} + type eventEntry struct { producer gen.PID token gen.Ref notify bool - // Buffer (simple slice - protected by mutex) - buffer []gen.MessageEvent - bufferSize int + // Ring buffer (nil if unbuffered, protected by mutex) + buffer *eventRingBuffer // Subscribers (links and monitors separately) // Slice for fast iteration, map for O(1) lookup/delete diff --git a/node/tm/query.go b/node/tm/query.go index 00dcb8a3d..13c0e6443 100644 --- a/node/tm/query.go +++ b/node/tm/query.go @@ -3,8 +3,8 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) HasLink(consumer gen.PID, target any) bool { - tm.mutex.Lock() - defer tm.mutex.Unlock() + tm.mutex.RLock() + defer tm.mutex.RUnlock() key := relationKey{ consumer: consumer, @@ -16,8 +16,8 @@ func (tm *targetManager) HasLink(consumer gen.PID, target any) bool { } func (tm *targetManager) HasMonitor(consumer gen.PID, target any) bool { - tm.mutex.Lock() - defer tm.mutex.Unlock() + tm.mutex.RLock() + defer tm.mutex.RUnlock() key := relationKey{ consumer: consumer, @@ -29,8 +29,8 @@ func (tm *targetManager) HasMonitor(consumer gen.PID, target any) bool { } func (tm *targetManager) LinksFor(consumer gen.PID) []any { - tm.mutex.Lock() - defer tm.mutex.Unlock() + tm.mutex.RLock() + defer tm.mutex.RUnlock() var targets []any @@ -44,8 +44,8 @@ func (tm *targetManager) LinksFor(consumer gen.PID) []any { } func (tm *targetManager) MonitorsFor(consumer gen.PID) []any { - tm.mutex.Lock() - defer tm.mutex.Unlock() + tm.mutex.RLock() + defer tm.mutex.RUnlock() var targets []any @@ -59,8 +59,8 @@ func (tm *targetManager) MonitorsFor(consumer gen.PID) []any { } func (tm *targetManager) EventsFor(producer gen.PID) []gen.Event { - tm.mutex.Lock() - defer tm.mutex.Unlock() + tm.mutex.RLock() + defer tm.mutex.RUnlock() // Use producerEvents index for O(1) lookup eventSet := tm.producerEvents[producer] diff --git a/node/tm/scenarios_test.go b/node/tm/scenarios_test.go index 8d42898f5..fc4dc7522 100644 --- a/node/tm/scenarios_test.go +++ b/node/tm/scenarios_test.go @@ -2223,7 +2223,7 @@ func TestCorner_PublishEvent_NoSubscribers(t *testing.T) { // Buffer updated entry := tm.events[event] - if len(entry.buffer) != 1 { + if entry.buffer.len != 1 { t.Error("Buffer should be updated") } } From 3bf2bacadbc8ee6b582c903c64ad42b6db592258 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 18 Mar 2026 01:22:41 +0100 Subject: [PATCH 052/122] improve tm --- node/tm/alias.go | 100 +++--- node/tm/alias_test.go | 105 +++--- node/tm/bench_test.go | 380 +++++++++++++++++++++ node/tm/event.go | 427 ++++++++++------------- node/tm/event_test.go | 130 +++---- node/tm/helpers_test.go | 74 ++++ node/tm/manager.go | 128 +++++-- node/tm/node.go | 74 ++-- node/tm/node_test.go | 80 ++--- node/tm/pid.go | 140 +++----- node/tm/pid_test.go | 86 ++--- node/tm/process_id.go | 101 +++--- node/tm/process_id_test.go | 104 +++--- node/tm/query.go | 67 ++-- node/tm/query_test.go | 106 +++--- node/tm/scenarios_test.go | 245 +++++++------- node/tm/terminate.go | 672 ++++++++++++++++--------------------- node/tm/terminate_test.go | 177 +++++----- 18 files changed, 1671 insertions(+), 1525 deletions(-) create mode 100644 node/tm/bench_test.go create mode 100644 node/tm/helpers_test.go diff --git a/node/tm/alias.go b/node/tm/alias.go index ca5a43c40..92d2b5d9b 100644 --- a/node/tm/alias.go +++ b/node/tm/alias.go @@ -3,25 +3,26 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) LinkAlias(consumer gen.PID, target gen.Alias) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists { - if consumer.Node != tm.core.Name() { - return nil - } - + _, exists := s.linkRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { @@ -29,7 +30,7 @@ func (tm *targetManager) LinkAlias(consumer gen.PID, target gen.Alias) error { allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } @@ -49,49 +50,45 @@ func (tm *targetManager) LinkAlias(consumer gen.PID, target gen.Alias) error { connection, err := tm.core.GetConnection(target.Node) if err != nil { - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.LinkAlias(tm.core.PID(), target) if err != nil { - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) UnlinkAlias(consumer gen.PID, target gen.Alias) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists == false { + if _, exists := s.linkRelations[key]; exists == false { return nil } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } @@ -99,9 +96,8 @@ func (tm *targetManager) UnlinkAlias(consumer gen.PID, target gen.Alias) error { delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } if target.Node == tm.core.Name() { @@ -116,7 +112,6 @@ func (tm *targetManager) UnlinkAlias(consumer gen.PID, target gen.Alias) error { break } } - if hasLocal { return nil } @@ -128,30 +123,30 @@ func (tm *targetManager) UnlinkAlias(consumer gen.PID, target gen.Alias) error { } connection.UnlinkAlias(tm.core.PID(), target) - return nil } func (tm *targetManager) MonitorAlias(consumer gen.PID, target gen.Alias) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists { - if consumer.Node != tm.core.Name() { - return nil - } - + _, exists := s.monitorRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { @@ -159,7 +154,7 @@ func (tm *targetManager) MonitorAlias(consumer gen.PID, target gen.Alias) error allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } @@ -179,49 +174,45 @@ func (tm *targetManager) MonitorAlias(consumer gen.PID, target gen.Alias) error connection, err := tm.core.GetConnection(target.Node) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.MonitorAlias(tm.core.PID(), target) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) DemonitorAlias(consumer gen.PID, target gen.Alias) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return nil } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } @@ -229,9 +220,8 @@ func (tm *targetManager) DemonitorAlias(consumer gen.PID, target gen.Alias) erro delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } if target.Node == tm.core.Name() { @@ -246,7 +236,6 @@ func (tm *targetManager) DemonitorAlias(consumer gen.PID, target gen.Alias) erro break } } - if hasLocal { return nil } @@ -258,6 +247,5 @@ func (tm *targetManager) DemonitorAlias(consumer gen.PID, target gen.Alias) erro } connection.DemonitorAlias(tm.core.PID(), target) - return nil } diff --git a/node/tm/alias_test.go b/node/tm/alias_test.go index c91f3cef8..3d57ac2d4 100644 --- a/node/tm/alias_test.go +++ b/node/tm/alias_test.go @@ -20,8 +20,7 @@ func TestLinkAlias_Local(t *testing.T) { t.Fatalf("LinkAlias failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should be stored") } @@ -43,13 +42,12 @@ func TestLinkAlias_Remote_First(t *testing.T) { } // Verify link stored in linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should be stored in linkRelations") } // Verify targetIndex created - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should be created") } @@ -92,20 +90,18 @@ func TestLinkAlias_Remote_Second(t *testing.T) { } // Verify both links stored in linkRelations - if len(tm.linkRelations) != 2 { - t.Errorf("Expected 2 link relations, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 2 { + t.Errorf("Expected 2 link relations, got %d", tm.totalLinks()) } - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, target); exists == false { t.Error("consumer1 link should exist in linkRelations") } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, target); exists == false { t.Error("consumer2 link should exist in linkRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -145,13 +141,12 @@ func TestLinkAlias_NetworkError_Rollback(t *testing.T) { } // Verify link rolled back from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be rolled back from linkRelations") } // Verify targetIndex cleaned after rollback - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -174,12 +169,12 @@ func TestLinkAlias_RemoteCorePID_Duplicate_Ignored(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored) - if len(tm.linkRelations) != 1 { - t.Errorf("Expected 1 link relation, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1 { + t.Errorf("Expected 1 link relation, got %d", tm.totalLinks()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -205,13 +200,12 @@ func TestUnlinkAlias_Local(t *testing.T) { } // Verify link removed from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed from linkRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned") } } @@ -232,19 +226,17 @@ func TestUnlinkAlias_NotLast(t *testing.T) { tm.UnlinkAlias(consumer1, target) // Verify consumer1 link removed from linkRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, target); exists { t.Error("consumer1 link should be removed from linkRelations") } // Verify consumer2 link still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, target); exists == false { t.Error("consumer2 link should still exist in linkRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } @@ -277,13 +269,12 @@ func TestUnlinkAlias_Last(t *testing.T) { } // Verify link removed from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed from linkRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -320,8 +311,7 @@ func TestMonitorAlias_Local(t *testing.T) { t.Fatalf("MonitorAlias failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should be stored") } @@ -343,13 +333,12 @@ func TestMonitorAlias_Remote_First(t *testing.T) { } // Verify monitor stored in monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should be stored in monitorRelations") } // Verify targetIndex created - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should be created") } @@ -392,20 +381,18 @@ func TestMonitorAlias_Remote_Second(t *testing.T) { } // Verify both monitors stored in monitorRelations - if len(tm.monitorRelations) != 2 { - t.Errorf("Expected 2 monitor relations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 2 { + t.Errorf("Expected 2 monitor relations, got %d", tm.totalMonitors()) } - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, target); exists == false { t.Error("consumer1 monitor should exist in monitorRelations") } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 monitor should exist in monitorRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -445,13 +432,12 @@ func TestMonitorAlias_NetworkError_Rollback(t *testing.T) { } // Verify monitor rolled back from monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be rolled back from monitorRelations") } // Verify targetIndex cleaned after rollback - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -474,12 +460,12 @@ func TestMonitorAlias_RemoteCorePID_Duplicate_Ignored(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored) - if len(tm.monitorRelations) != 1 { - t.Errorf("Expected 1 monitor relation, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 1 { + t.Errorf("Expected 1 monitor relation, got %d", tm.totalMonitors()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -505,13 +491,12 @@ func TestDemonitorAlias_Local(t *testing.T) { } // Verify monitor removed from monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be removed from monitorRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned") } } @@ -532,19 +517,17 @@ func TestDemonitorAlias_NotLast(t *testing.T) { tm.DemonitorAlias(consumer1, target) // Verify consumer1 monitor removed from monitorRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists { + if exists := tm.hasMonitorRelation(consumer1, target); exists { t.Error("consumer1 monitor should be removed from monitorRelations") } // Verify consumer2 monitor still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 monitor should still exist in monitorRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } @@ -577,13 +560,12 @@ func TestDemonitorAlias_Last(t *testing.T) { } // Verify monitor removed from monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be removed from monitorRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -611,8 +593,7 @@ func TestDemonitorAlias_Complete(t *testing.T) { } // consumer2 still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("Second monitor should still exist") } @@ -623,11 +604,11 @@ func TestDemonitorAlias_Complete(t *testing.T) { } // All cleaned - if len(tm.monitorRelations) != 0 { + if tm.totalMonitors() != 0 { t.Error("All monitors should be cleaned") } - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned") } } diff --git a/node/tm/bench_test.go b/node/tm/bench_test.go new file mode 100644 index 000000000..bd11d3400 --- /dev/null +++ b/node/tm/bench_test.go @@ -0,0 +1,380 @@ +package tm + +import ( + "fmt" + "sync" + "sync/atomic" + "testing" + "time" + + "ergo.services/ergo/gen" +) + +func benchTM(nodeName string) (*targetManager, *mockCore) { + core := newMockCore(nodeName) + tm := Create(core, Options{}).(*targetManager) + return tm, core +} + +func makePID(node string, id uint64) gen.PID { + return gen.PID{Node: gen.Atom(node), ID: id, Creation: 1} +} + +func makeEvent(node string, name string) gen.Event { + return gen.Event{Node: gen.Atom(node), Name: gen.Atom(name)} +} + +func BenchmarkLinkPID_Local(b *testing.B) { + tm, _ := benchTM("node1") + target := makePID("node1", 100) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + consumer := makePID("node1", uint64(i+1000)) + tm.LinkPID(consumer, target) + } +} + +func BenchmarkMonitorPID_Local(b *testing.B) { + tm, _ := benchTM("node1") + target := makePID("node1", 100) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + consumer := makePID("node1", uint64(i+1000)) + tm.MonitorPID(consumer, target) + } +} + +func BenchmarkPublishEvent_NoSubscribers(b *testing.B) { + tm, _ := benchTM("node1") + producer := makePID("node1", 10) + token, _ := tm.RegisterEvent(producer, "bench_event", gen.EventOptions{}) + event := makeEvent("node1", "bench_event") + + msg := gen.MessageEvent{Event: event} + opts := gen.MessageOptions{} + + b.ResetTimer() + for i := 0; i < b.N; i++ { + tm.PublishEvent(producer, token, opts, msg) + } +} + +func BenchmarkPublishEvent_10Subscribers(b *testing.B) { + tm, _ := benchTM("node1") + producer := makePID("node1", 10) + token, _ := tm.RegisterEvent(producer, "bench_event", gen.EventOptions{}) + event := makeEvent("node1", "bench_event") + + for i := 0; i < 10; i++ { + consumer := makePID("node1", uint64(i+100)) + tm.LinkEvent(consumer, event) + } + + msg := gen.MessageEvent{Event: event} + opts := gen.MessageOptions{} + + b.ResetTimer() + for i := 0; i < b.N; i++ { + tm.PublishEvent(producer, token, opts, msg) + } +} + +func BenchmarkPublishEvent_100Subscribers(b *testing.B) { + tm, _ := benchTM("node1") + producer := makePID("node1", 10) + token, _ := tm.RegisterEvent(producer, "bench_event", gen.EventOptions{}) + event := makeEvent("node1", "bench_event") + + for i := 0; i < 100; i++ { + consumer := makePID("node1", uint64(i+100)) + tm.LinkEvent(consumer, event) + } + + msg := gen.MessageEvent{Event: event} + opts := gen.MessageOptions{} + + b.ResetTimer() + for i := 0; i < b.N; i++ { + tm.PublishEvent(producer, token, opts, msg) + } +} + +func BenchmarkHasLink(b *testing.B) { + tm, _ := benchTM("node1") + consumer := makePID("node1", 1) + target := makePID("node1", 100) + tm.LinkPID(consumer, target) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + tm.HasLink(consumer, target) + } +} + +func BenchmarkLinkPID_Parallel(b *testing.B) { + tm, _ := benchTM("node1") + + b.RunParallel(func(pb *testing.PB) { + id := uint64(0) + for pb.Next() { + id++ + consumer := makePID("node1", id+10000) + target := makePID("node1", id) + tm.LinkPID(consumer, target) + } + }) +} + +func BenchmarkPublishEvent_Parallel(b *testing.B) { + tm, _ := benchTM("node1") + producer := makePID("node1", 10) + token, _ := tm.RegisterEvent(producer, "bench_event", gen.EventOptions{}) + event := makeEvent("node1", "bench_event") + + for i := 0; i < 10; i++ { + consumer := makePID("node1", uint64(i+100)) + tm.LinkEvent(consumer, event) + } + + msg := gen.MessageEvent{Event: event} + opts := gen.MessageOptions{} + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + tm.PublishEvent(producer, token, opts, msg) + } + }) +} + +func BenchmarkContention_PublishWhileMonitor(b *testing.B) { + tm, _ := benchTM("node1") + + type eventInfo struct { + producer gen.PID + token gen.Ref + event gen.Event + } + var events []eventInfo + + for e := 0; e < 10; e++ { + producer := makePID("node1", uint64(e+1)) + name := gen.Atom(fmt.Sprintf("event_%d", e)) + token, _ := tm.RegisterEvent(producer, name, gen.EventOptions{}) + event := gen.Event{Node: "node1", Name: name} + + for s := 0; s < 10; s++ { + consumer := makePID("node1", uint64(e*100+s+1000)) + tm.LinkEvent(consumer, event) + } + + events = append(events, eventInfo{producer: producer, token: token, event: event}) + } + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + id := uint64(0) + for pb.Next() { + id++ + if id%2 == 0 { + ei := events[id%uint64(len(events))] + msg := gen.MessageEvent{Event: ei.event} + tm.PublishEvent(ei.producer, ei.token, gen.MessageOptions{}, msg) + } else { + consumer := makePID("node1", id+50000) + target := makePID("node1", id) + tm.MonitorPID(consumer, target) + } + } + }) +} + +func BenchmarkTerminatedTargetPID(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + tm, _ := benchTM("node1") + target := makePID("node1", 100) + + for c := 0; c < 10; c++ { + consumer := makePID("node1", uint64(c+1)) + tm.LinkPID(consumer, target) + } + + b.StartTimer() + tm.TerminatedTargetPID(target, fmt.Errorf("test")) + } +} + +func BenchmarkTerminatedProcess(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + tm, _ := benchTM("node1") + consumer := makePID("node1", 1) + + for t := 0; t < 100; t++ { + target := makePID("node1", uint64(t+100)) + tm.LinkPID(consumer, target) + } + + b.StartTimer() + tm.TerminatedProcess(consumer, fmt.Errorf("test")) + } +} + +func BenchmarkTerminatedTargetNode(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + tm, _ := benchTM("node1") + + for c := 0; c < 100; c++ { + consumer := makePID("node1", uint64(c+1)) + target := makePID("node2", uint64(c+1)) + s := tm.shardFor(target) + key := relationKey{consumer: consumer, target: target} + s.linkRelations[key] = struct{}{} + entry := &targetEntry{consumers: make(map[gen.PID]struct{})} + entry.consumers[consumer] = struct{}{} + s.targetIndex[target] = entry + } + + b.StartTimer() + tm.TerminatedTargetNode("node2", fmt.Errorf("test")) + } +} + +func BenchmarkContention_TerminateNodeWhileMonitor(b *testing.B) { + tm, _ := benchTM("node1") + + for c := 0; c < 100; c++ { + consumer := makePID("node1", uint64(c+1)) + target := makePID("node2", uint64(c+1)) + s := tm.shardFor(target) + key := relationKey{consumer: consumer, target: target} + s.linkRelations[key] = struct{}{} + entry := &targetEntry{consumers: make(map[gen.PID]struct{})} + entry.consumers[consumer] = struct{}{} + s.targetIndex[target] = entry + } + + b.ResetTimer() + + var wg sync.WaitGroup + wg.Add(1) + + done := make(chan struct{}) + go func() { + defer wg.Done() + id := uint64(0) + for { + select { + case <-done: + return + default: + id++ + consumer := makePID("node1", id+90000) + target := makePID("node1", id+80000) + tm.MonitorPID(consumer, target) + } + } + }() + + for i := 0; i < b.N; i++ { + tm.TerminatedTargetNode("node2", fmt.Errorf("test")) + + for c := 0; c < 100; c++ { + consumer := makePID("node1", uint64(c+1)) + target := makePID("node2", uint64(c+1)) + s := tm.shardFor(target) + s.mutex.Lock() + key := relationKey{consumer: consumer, target: target} + s.linkRelations[key] = struct{}{} + entry := &targetEntry{consumers: make(map[gen.PID]struct{})} + entry.consumers[consumer] = struct{}{} + s.targetIndex[target] = entry + s.mutex.Unlock() + } + } + + close(done) + wg.Wait() +} + +// BenchmarkMonitorLatencyUnderPublishLoad measures MonitorPID latency +// while N goroutines continuously publish events. +// This simulates the real bottleneck: sustained publish pressure starving MonitorPID. +func BenchmarkMonitorLatencyUnderPublishLoad(b *testing.B) { + for _, publishers := range []int{1, 4, 8, 14} { + b.Run(fmt.Sprintf("publishers=%d", publishers), func(b *testing.B) { + tm, _ := benchTM("node1") + + // Register events, one per publisher + type pubInfo struct { + producer gen.PID + token gen.Ref + event gen.Event + msg gen.MessageEvent + } + pubs := make([]pubInfo, publishers) + for i := 0; i < publishers; i++ { + producer := makePID("node1", uint64(i+1)) + name := gen.Atom(fmt.Sprintf("event_%d", i)) + token, _ := tm.RegisterEvent(producer, name, gen.EventOptions{}) + event := gen.Event{Node: "node1", Name: name} + + // 20 subscribers per event + for s := 0; s < 20; s++ { + consumer := makePID("node1", uint64(i*100+s+1000)) + tm.LinkEvent(consumer, event) + } + + pubs[i] = pubInfo{ + producer: producer, + token: token, + event: event, + msg: gen.MessageEvent{Event: event}, + } + } + + // Start publishers - they publish non-stop + stop := make(chan struct{}) + var publishCount atomic.Int64 + var publisherWg sync.WaitGroup + + for i := 0; i < publishers; i++ { + publisherWg.Add(1) + go func(p pubInfo) { + defer publisherWg.Done() + opts := gen.MessageOptions{} + for { + select { + case <-stop: + return + default: + tm.PublishEvent(p.producer, p.token, opts, p.msg) + publishCount.Add(1) + } + } + }(pubs[i]) + } + + // Let publishers warm up + time.Sleep(10 * time.Millisecond) + + // Benchmark: measure MonitorPID latency under load + b.ResetTimer() + for i := 0; i < b.N; i++ { + consumer := makePID("node1", uint64(i+500000)) + target := makePID("node1", uint64(i+600000)) + tm.MonitorPID(consumer, target) + } + b.StopTimer() + + close(stop) + publisherWg.Wait() + + b.ReportMetric(float64(publishCount.Load())/float64(b.N), "publishes/monitor") + }) + } +} diff --git a/node/tm/event.go b/node/tm/event.go index 0a67a409d..9dbc4fd2d 100644 --- a/node/tm/event.go +++ b/node/tm/event.go @@ -1,30 +1,21 @@ package tm import ( - "time" - "ergo.services/ergo/gen" ) func (tm *targetManager) RegisterEvent(producer gen.PID, name gen.Atom, options gen.EventOptions) (gen.Ref, error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() - event := gen.Event{Node: tm.core.Name(), Name: name} + s := tm.shardFor(event) + s.mutex.Lock() + defer s.mutex.Unlock() - // Check if already exists - if _, exists := tm.events[event]; exists { + if _, exists := s.events[event]; exists { return gen.Ref{}, gen.ErrTaken } - // Generate unique token - token := gen.Ref{ - Node: tm.core.Name(), - Creation: tm.core.PID().Creation, - ID: [3]uint64{uint64(time.Now().UnixNano()), 0, 0}, - } + token := tm.generateToken() - // Create event entry entry := &eventEntry{ producer: producer, token: token, @@ -34,7 +25,6 @@ func (tm *targetManager) RegisterEvent(producer gen.PID, name gen.Atom, options subscriberCount: 0, } - // Create ring buffer if configured if options.Buffer > 0 { entry.buffer = &eventRingBuffer{ data: make([]gen.MessageEvent, options.Buffer), @@ -42,53 +32,79 @@ func (tm *targetManager) RegisterEvent(producer gen.PID, name gen.Atom, options } } - tm.events[event] = entry + s.events[event] = entry - // Add to producerEvents index - if tm.producerEvents[producer] == nil { - tm.producerEvents[producer] = make(map[gen.Event]struct{}) + if s.producerEvents[producer] == nil { + s.producerEvents[producer] = make(map[gen.Event]struct{}) } - tm.producerEvents[producer][event] = struct{}{} + s.producerEvents[producer][event] = struct{}{} return token, nil } func (tm *targetManager) UnregisterEvent(producer gen.PID, name gen.Atom) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() - event := gen.Event{Node: tm.core.Name(), Name: name} - entry, exists := tm.events[event] + s := tm.shardFor(event) + s.mutex.Lock() + + entry, exists := s.events[event] if exists == false { + s.mutex.Unlock() return gen.ErrEventUnknown } if entry.producer != producer { + s.mutex.Unlock() return gen.ErrEventOwner } - // Collect all subscribers (links + monitors) remoteNodes := make(map[gen.Atom]bool) var localExitConsumers []gen.PID var localDownConsumers []gen.PID for _, consumer := range entry.linkSubscribers { - if consumer.Node == tm.core.Name() { - localExitConsumers = append(localExitConsumers, consumer) - } else { + if consumer.Node != tm.core.Name() { remoteNodes[consumer.Node] = true + continue } + localExitConsumers = append(localExitConsumers, consumer) } for _, consumer := range entry.monitorSubscribers { - if consumer.Node == tm.core.Name() { - localDownConsumers = append(localDownConsumers, consumer) - } else { + if consumer.Node != tm.core.Name() { remoteNodes[consumer.Node] = true + continue + } + localDownConsumers = append(localDownConsumers, consumer) + } + + // Cleanup relations + for key := range s.linkRelations { + if key.target == event { + delete(s.linkRelations, key) + } + } + + for key := range s.monitorRelations { + if key.target == event { + delete(s.monitorRelations, key) } } - // Send exit messages to local link subscribers + delete(s.events, event) + delete(s.targetIndex, event) + + events := s.producerEvents[producer] + if events != nil { + delete(events, event) + if len(events) == 0 { + delete(s.producerEvents, producer) + } + } + + s.mutex.Unlock() + + // Dispatch without lock if len(localExitConsumers) > 0 { tm.core.RouteSendExitMessages( tm.core.PID(), @@ -97,7 +113,6 @@ func (tm *targetManager) UnregisterEvent(producer gen.PID, name gen.Atom) error ) } - // Send down messages to local monitor subscribers for _, consumer := range localDownConsumers { tm.core.RouteSendPID( tm.core.PID(), @@ -107,7 +122,6 @@ func (tm *targetManager) UnregisterEvent(producer gen.PID, name gen.Atom) error ) } - // Send to remote nodes for node := range remoteNodes { connection, err := tm.core.GetConnection(node) if err != nil { @@ -116,33 +130,6 @@ func (tm *targetManager) UnregisterEvent(producer gen.PID, name gen.Atom) error connection.SendTerminateEvent(event, gen.ErrUnregistered) } - // Cleanup event - delete(tm.events, event) - - // Cleanup producerEvents index - if events := tm.producerEvents[producer]; events != nil { - delete(events, event) - if len(events) == 0 { - delete(tm.producerEvents, producer) - } - } - - // Cleanup relations - for key := range tm.linkRelations { - if key.target == event { - delete(tm.linkRelations, key) - } - } - - for key := range tm.monitorRelations { - if key.target == event { - delete(tm.monitorRelations, key) - } - } - - // Cleanup targetIndex - delete(tm.targetIndex, event) - return nil } @@ -152,16 +139,14 @@ func (tm *targetManager) PublishEvent( options gen.MessageOptions, message gen.MessageEvent, ) error { - // Check if this is a LOCAL producer or REMOTE event if from.Node == tm.core.Name() { - // LOCAL producer - needs Lock (writes to buffer) return tm.publishEventLocalProducer(from, token, options, message) } - // REMOTE event - needs only RLock (read-only) - tm.mutex.RLock() - defer tm.mutex.RUnlock() - return tm.publishEventRemoteProducer(from, options, message) + s := tm.shardFor(message.Event) + s.mutex.RLock() + defer s.mutex.RUnlock() + return tm.publishEventRemoteProducer(s, from, options, message) } func (tm *targetManager) publishEventLocalProducer( @@ -170,47 +155,38 @@ func (tm *targetManager) publishEventLocalProducer( options gen.MessageOptions, message gen.MessageEvent, ) error { - tm.mutex.Lock() + s := tm.shardFor(message.Event) + s.mutex.RLock() - entry, exists := tm.events[message.Event] + entry, exists := s.events[message.Event] if exists == false { - tm.mutex.Unlock() + s.mutex.RUnlock() return gen.ErrEventUnknown } - // Validate token if entry.token != token { - tm.mutex.Unlock() + s.mutex.RUnlock() return gen.ErrEventOwner } - // Store in ring buffer if configured (needs write lock) if entry.buffer != nil { - // Re-check after lock upgrade - entry, exists = tm.events[message.Event] - if exists == false || entry.token != token { - tm.mutex.Unlock() - return gen.ErrEventOwner - } + entry.bufferMutex.Lock() entry.buffer.push(message) + entry.bufferMutex.Unlock() } - // Increment per-event published counter under lock entry.messagesPublished.Add(1) - // Copy slices under lock (minimize lock hold time) + // Snapshot slices under RLock (safe: slices only modified under write lock) linkSubs := entry.linkSubscribers monitorSubs := entry.monitorSubscribers - tm.mutex.Unlock() + s.mutex.RUnlock() - // Increment global published counter tm.eventsPublished.Add(1) - // Collect local consumers and remote nodes (no lock needed) var localConsumers []gen.PID remoteNodes := make(map[gen.Atom]bool) - // Fanout to link subscribers for _, consumer := range linkSubs { if consumer.Node != tm.core.Name() { remoteNodes[consumer.Node] = true @@ -219,7 +195,6 @@ func (tm *targetManager) publishEventLocalProducer( localConsumers = append(localConsumers, consumer) } - // Fanout to monitor subscribers for _, consumer := range monitorSubs { if consumer.Node != tm.core.Name() { remoteNodes[consumer.Node] = true @@ -228,7 +203,6 @@ func (tm *targetManager) publishEventLocalProducer( localConsumers = append(localConsumers, consumer) } - // Send to local consumers directly if len(localConsumers) > 0 { tm.core.RouteSendEventMessages(from, localConsumers, options, message) n := int64(len(localConsumers)) @@ -236,7 +210,6 @@ func (tm *targetManager) publishEventLocalProducer( tm.eventsLocalSent.Add(n) } - // Send to remote nodes for node := range remoteNodes { connection, err := tm.core.GetConnection(node) if err != nil { @@ -251,26 +224,24 @@ func (tm *targetManager) publishEventLocalProducer( } func (tm *targetManager) publishEventRemoteProducer( + s *shard, from gen.PID, options gen.MessageOptions, message gen.MessageEvent, ) error { - // Remote event arrived - deliver to local subscribers only - entry := tm.targetIndex[message.Event] + entry := s.targetIndex[message.Event] if entry == nil { return nil } - // Increment received counter (remote event arrival, not a local publish) tm.eventsReceived.Add(1) - // Collect local consumers for batch delivery var localConsumers []gen.PID - for consumer := range entry.consumers { - if consumer.Node == tm.core.Name() { - localConsumers = append(localConsumers, consumer) + if consumer.Node != tm.core.Name() { + continue } + localConsumers = append(localConsumers, consumer) } if len(localConsumers) > 0 { @@ -282,21 +253,19 @@ func (tm *targetManager) publishEventRemoteProducer( } func (tm *targetManager) LinkEvent(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(event) + s.mutex.Lock() + defer s.mutex.Unlock() - // Check if local or remote event if event.Node == tm.core.Name() { - // LOCAL event - return tm.linkEventLocal(consumer, event) + return tm.linkEventLocal(s, consumer, event) } - // REMOTE event - return tm.linkEventRemote(consumer, event) + return tm.linkEventRemote(s, consumer, event) } -func (tm *targetManager) linkEventLocal(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { - entry, exists := tm.events[event] +func (tm *targetManager) linkEventLocal(s *shard, consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { + entry, exists := s.events[event] if exists == false { return nil, gen.ErrEventUnknown } @@ -306,26 +275,20 @@ func (tm *targetManager) linkEventLocal(consumer gen.PID, event gen.Event) ([]ge target: event, } - // Check duplicate - if _, exists := tm.linkRelations[key]; exists { - // For local event, duplicate from REMOTE CorePID is allowed - if consumer.Node != tm.core.Name() { - // Remote CorePID - return buffer anyway - return tm.getEventBuffer(entry), nil - } - + _, dup := s.linkRelations[key] + if dup == true && consumer.Node != tm.core.Name() { + return getEventBuffer(entry), nil + } + if dup == true { return nil, gen.ErrTargetExist } - // Add subscription - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} entry.linkSubscribersIndex[consumer] = len(entry.linkSubscribers) entry.linkSubscribers = append(entry.linkSubscribers, consumer) - // Increment counter entry.subscriberCount++ - // Check if need to send EventStart if entry.subscriberCount == 1 && entry.notify { tm.core.RouteSendPID( tm.core.PID(), @@ -335,38 +298,33 @@ func (tm *targetManager) linkEventLocal(consumer gen.PID, event gen.Event) ([]ge ) } - // Return buffer - return tm.getEventBuffer(entry), nil + return getEventBuffer(entry), nil } -func (tm *targetManager) linkEventRemote(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { +func (tm *targetManager) linkEventRemote(s *shard, consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { key := relationKey{ consumer: consumer, target: event, } - if _, exists := tm.linkRelations[key]; exists { + if _, exists := s.linkRelations[key]; exists { return nil, gen.ErrTargetExist } - // Add subscription locally - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} - // Check targetIndex for remote request decision - entry := tm.targetIndex[event] + entry := s.targetIndex[event] needsRemote := false if entry == nil { - // First subscriber entry = &targetEntry{ - allowAlwaysFirst: true, // Start with true for buffered events + allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[event] = entry + s.targetIndex[event] = entry needsRemote = true } - // For events, allowAlwaysFirst stays true for buffered! if entry.allowAlwaysFirst == true { needsRemote = true } @@ -374,62 +332,50 @@ func (tm *targetManager) linkEventRemote(consumer gen.PID, event gen.Event) ([]g entry.consumers[consumer] = struct{}{} if needsRemote == false { - // Unbuffered event, not first - no remote request return nil, nil } - // Send remote LinkEvent connection, err := tm.core.GetConnection(event.Node) if err != nil { - // Rollback - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } - return nil, err } buffer, err := connection.LinkEvent(tm.core.PID(), event) if err != nil { - // Rollback - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } - return nil, err } - // Success! - // If buffer == nil: unbuffered, set allowAlwaysFirst=false - // If buffer != nil: buffered, keep allowAlwaysFirst=true if buffer == nil { entry.allowAlwaysFirst = false } - // else: buffered, keep allowAlwaysFirst=true for next subscribers! return buffer, nil } func (tm *targetManager) UnlinkEvent(consumer gen.PID, event gen.Event) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(event) + s.mutex.Lock() + defer s.mutex.Unlock() - // Check if local or remote if event.Node == tm.core.Name() { - return tm.unlinkEventLocal(consumer, event) + return tm.unlinkEventLocal(s, consumer, event) } - return tm.unlinkEventRemote(consumer, event) + return tm.unlinkEventRemote(s, consumer, event) } -func (tm *targetManager) unlinkEventLocal(consumer gen.PID, event gen.Event) error { - entry, exists := tm.events[event] +func (tm *targetManager) unlinkEventLocal(s *shard, consumer gen.PID, event gen.Event) error { + entry, exists := s.events[event] if exists == false { return gen.ErrEventUnknown } @@ -439,12 +385,11 @@ func (tm *targetManager) unlinkEventLocal(consumer gen.PID, event gen.Event) err target: event, } - if _, exists := tm.linkRelations[key]; exists == false { + if _, exists := s.linkRelations[key]; exists == false { return gen.ErrTargetUnknown } - // Remove subscription - delete(tm.linkRelations, key) + delete(s.linkRelations, key) // Swap-delete from slice idx := entry.linkSubscribersIndex[consumer] @@ -456,10 +401,8 @@ func (tm *targetManager) unlinkEventLocal(consumer gen.PID, event gen.Event) err entry.linkSubscribers = entry.linkSubscribers[:last] delete(entry.linkSubscribersIndex, consumer) - // Decrement counter entry.subscriberCount-- - // Send EventStop if last subscriber if entry.subscriberCount == 0 && entry.notify { tm.core.RouteSendPID( tm.core.PID(), @@ -472,19 +415,19 @@ func (tm *targetManager) unlinkEventLocal(consumer gen.PID, event gen.Event) err return nil } -func (tm *targetManager) unlinkEventRemote(consumer gen.PID, event gen.Event) error { +func (tm *targetManager) unlinkEventRemote(s *shard, consumer gen.PID, event gen.Event) error { key := relationKey{ consumer: consumer, target: event, } - if _, exists := tm.linkRelations[key]; exists == false { + if _, exists := s.linkRelations[key]; exists == false { return gen.ErrTargetUnknown } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - entry := tm.targetIndex[event] + entry := s.targetIndex[event] if entry == nil { return nil } @@ -492,12 +435,10 @@ func (tm *targetManager) unlinkEventRemote(consumer gen.PID, event gen.Event) er delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } - // Check if need to send remote UnlinkEvent if isLast == false { hasLocal := false for pid := range entry.consumers { @@ -506,37 +447,34 @@ func (tm *targetManager) unlinkEventRemote(consumer gen.PID, event gen.Event) er break } } - if hasLocal { return nil } } - // Last local consumer - send remote UnlinkEvent connection, err := tm.core.GetConnection(event.Node) if err != nil { return nil } connection.UnlinkEvent(tm.core.PID(), event) - return nil } func (tm *targetManager) MonitorEvent(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(event) + s.mutex.Lock() + defer s.mutex.Unlock() - // Same logic as LinkEvent, but for monitors if event.Node == tm.core.Name() { - return tm.monitorEventLocal(consumer, event) + return tm.monitorEventLocal(s, consumer, event) } - return tm.monitorEventRemote(consumer, event) + return tm.monitorEventRemote(s, consumer, event) } -func (tm *targetManager) monitorEventLocal(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { - entry, exists := tm.events[event] +func (tm *targetManager) monitorEventLocal(s *shard, consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { + entry, exists := s.events[event] if exists == false { return nil, gen.ErrEventUnknown } @@ -546,24 +484,20 @@ func (tm *targetManager) monitorEventLocal(consumer gen.PID, event gen.Event) ([ target: event, } - if _, exists := tm.monitorRelations[key]; exists { - if consumer.Node != tm.core.Name() { - // Remote CorePID duplicate - return buffer - return tm.getEventBuffer(entry), nil - } - + _, dup := s.monitorRelations[key] + if dup == true && consumer.Node != tm.core.Name() { + return getEventBuffer(entry), nil + } + if dup == true { return nil, gen.ErrTargetExist } - // Add subscription - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} entry.monitorSubscribersIndex[consumer] = len(entry.monitorSubscribers) entry.monitorSubscribers = append(entry.monitorSubscribers, consumer) - // Increment counter (shared with links!) entry.subscriberCount++ - // Send EventStart if first subscriber overall if entry.subscriberCount == 1 && entry.notify { tm.core.RouteSendPID( tm.core.PID(), @@ -573,23 +507,22 @@ func (tm *targetManager) monitorEventLocal(consumer gen.PID, event gen.Event) ([ ) } - // Return buffer - return tm.getEventBuffer(entry), nil + return getEventBuffer(entry), nil } -func (tm *targetManager) monitorEventRemote(consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { +func (tm *targetManager) monitorEventRemote(s *shard, consumer gen.PID, event gen.Event) ([]gen.MessageEvent, error) { key := relationKey{ consumer: consumer, target: event, } - if _, exists := tm.monitorRelations[key]; exists { + if _, exists := s.monitorRelations[key]; exists { return nil, gen.ErrTargetExist } - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} - entry := tm.targetIndex[event] + entry := s.targetIndex[event] needsRemote := false if entry == nil { @@ -597,7 +530,7 @@ func (tm *targetManager) monitorEventRemote(consumer gen.PID, event gen.Event) ( allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[event] = entry + s.targetIndex[event] = entry needsRemote = true } @@ -613,29 +546,24 @@ func (tm *targetManager) monitorEventRemote(consumer gen.PID, event gen.Event) ( connection, err := tm.core.GetConnection(event.Node) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } - return nil, err } buffer, err := connection.MonitorEvent(tm.core.PID(), event) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } - return nil, err } - // Buffered vs unbuffered if buffer == nil { entry.allowAlwaysFirst = false } @@ -644,18 +572,19 @@ func (tm *targetManager) monitorEventRemote(consumer gen.PID, event gen.Event) ( } func (tm *targetManager) DemonitorEvent(consumer gen.PID, event gen.Event) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(event) + s.mutex.Lock() + defer s.mutex.Unlock() if event.Node == tm.core.Name() { - return tm.demonitorEventLocal(consumer, event) + return tm.demonitorEventLocal(s, consumer, event) } - return tm.demonitorEventRemote(consumer, event) + return tm.demonitorEventRemote(s, consumer, event) } -func (tm *targetManager) demonitorEventLocal(consumer gen.PID, event gen.Event) error { - entry, exists := tm.events[event] +func (tm *targetManager) demonitorEventLocal(s *shard, consumer gen.PID, event gen.Event) error { + entry, exists := s.events[event] if exists == false { return gen.ErrEventUnknown } @@ -665,11 +594,11 @@ func (tm *targetManager) demonitorEventLocal(consumer gen.PID, event gen.Event) target: event, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return gen.ErrTargetUnknown } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) // Swap-delete from slice idx := entry.monitorSubscribersIndex[consumer] @@ -681,10 +610,8 @@ func (tm *targetManager) demonitorEventLocal(consumer gen.PID, event gen.Event) entry.monitorSubscribers = entry.monitorSubscribers[:last] delete(entry.monitorSubscribersIndex, consumer) - // Decrement counter (shared with links!) entry.subscriberCount-- - // Send EventStop if last if entry.subscriberCount == 0 && entry.notify { tm.core.RouteSendPID( tm.core.PID(), @@ -697,19 +624,19 @@ func (tm *targetManager) demonitorEventLocal(consumer gen.PID, event gen.Event) return nil } -func (tm *targetManager) demonitorEventRemote(consumer gen.PID, event gen.Event) error { +func (tm *targetManager) demonitorEventRemote(s *shard, consumer gen.PID, event gen.Event) error { key := relationKey{ consumer: consumer, target: event, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return gen.ErrTargetUnknown } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[event] + entry := s.targetIndex[event] if entry == nil { return nil } @@ -717,9 +644,8 @@ func (tm *targetManager) demonitorEventRemote(consumer gen.PID, event gen.Event) delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, event) + delete(s.targetIndex, event) } if isLast == false { @@ -730,7 +656,6 @@ func (tm *targetManager) demonitorEventRemote(consumer gen.PID, event gen.Event) break } } - if hasLocal { return nil } @@ -742,26 +667,26 @@ func (tm *targetManager) demonitorEventRemote(consumer gen.PID, event gen.Event) } connection.DemonitorEvent(tm.core.PID(), event) - return nil } func (tm *targetManager) EventInfo(event gen.Event) (gen.EventInfo, error) { - tm.mutex.RLock() - defer tm.mutex.RUnlock() + s := tm.shardFor(event) + s.mutex.RLock() + defer s.mutex.RUnlock() - entry, exists := tm.events[event] + entry, exists := s.events[event] if exists == false { return gen.EventInfo{}, gen.ErrEventUnknown } - // Build event info var bufSize, bufLen int if entry.buffer != nil { bufSize = entry.buffer.size bufLen = entry.buffer.len } - info := gen.EventInfo{ + + return gen.EventInfo{ Event: event, Producer: entry.producer, BufferSize: bufSize, @@ -771,38 +696,36 @@ func (tm *targetManager) EventInfo(event gen.Event) (gen.EventInfo, error) { MessagesPublished: entry.messagesPublished.Load(), MessagesLocalSent: entry.messagesLocalSent.Load(), MessagesRemoteSent: entry.messagesRemoteSent.Load(), - } - - return info, nil + }, nil } func (tm *targetManager) EventRangeInfo(fn func(gen.EventInfo) bool) error { - tm.mutex.RLock() - - // Snapshot event infos under lock - infos := make([]gen.EventInfo, 0, len(tm.events)) - for event, entry := range tm.events { - var bufSize, bufLen int - if entry.buffer != nil { - bufSize = entry.buffer.size - bufLen = entry.buffer.len - } - info := gen.EventInfo{ - Event: event, - Producer: entry.producer, - BufferSize: bufSize, - CurrentBuffer: bufLen, - Notify: entry.notify, - Subscribers: entry.subscriberCount, - MessagesPublished: entry.messagesPublished.Load(), - MessagesLocalSent: entry.messagesLocalSent.Load(), - MessagesRemoteSent: entry.messagesRemoteSent.Load(), + var infos []gen.EventInfo + + for i := range tm.shards { + s := &tm.shards[i] + s.mutex.RLock() + for event, entry := range s.events { + var bufSize, bufLen int + if entry.buffer != nil { + bufSize = entry.buffer.size + bufLen = entry.buffer.len + } + infos = append(infos, gen.EventInfo{ + Event: event, + Producer: entry.producer, + BufferSize: bufSize, + CurrentBuffer: bufLen, + Notify: entry.notify, + Subscribers: entry.subscriberCount, + MessagesPublished: entry.messagesPublished.Load(), + MessagesLocalSent: entry.messagesLocalSent.Load(), + MessagesRemoteSent: entry.messagesRemoteSent.Load(), + }) } - infos = append(infos, info) + s.mutex.RUnlock() } - tm.mutex.RUnlock() - // Iterate without lock for _, info := range infos { if fn(info) == false { break @@ -811,11 +734,3 @@ func (tm *targetManager) EventRangeInfo(fn func(gen.EventInfo) bool) error { return nil } - -// Helper: get event buffer snapshot -func (tm *targetManager) getEventBuffer(entry *eventEntry) []gen.MessageEvent { - if entry.buffer == nil { - return nil - } - return entry.buffer.snapshot() -} diff --git a/node/tm/event_test.go b/node/tm/event_test.go index b1032de7d..025b92b29 100644 --- a/node/tm/event_test.go +++ b/node/tm/event_test.go @@ -26,7 +26,7 @@ func TestRegisterEvent_Basic(t *testing.T) { // Verify event stored event := gen.Event{Node: "node1", Name: "test"} - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry == nil { t.Fatal("Event should be stored") } @@ -99,7 +99,7 @@ func TestLinkEvent_Local_FirstSubscriber_EventStart(t *testing.T) { } // Verify stored - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 1 { t.Errorf("subscriberCount should be 1, got %d", entry.subscriberCount) } @@ -133,7 +133,7 @@ func TestLinkEvent_Local_SecondSubscriber_NoEventStart(t *testing.T) { } // Counter = 2 - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 2 { t.Errorf("subscriberCount should be 2, got %d", entry.subscriberCount) } @@ -170,7 +170,7 @@ func TestUnlinkEvent_Local_LastSubscriber_EventStop(t *testing.T) { } // Counter = 0 - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 0 { t.Errorf("subscriberCount should be 0, got %d", entry.subscriberCount) } @@ -191,8 +191,7 @@ func TestLinkEvent_Remote_FirstSubscriber(t *testing.T) { } // Verify stored locally - key := relationKey{consumer: consumer, target: event} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, event); exists == false { t.Error("Link should be stored locally") } @@ -202,7 +201,7 @@ func TestLinkEvent_Remote_FirstSubscriber(t *testing.T) { } // Verify allowAlwaysFirst=false (unbuffered) - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry.allowAlwaysFirst == true { t.Error("allowAlwaysFirst should be false for unbuffered event") } @@ -234,18 +233,16 @@ func TestLinkEvent_Remote_SecondSubscriber_Unbuffered_NoNetwork(t *testing.T) { } // Verify both links stored in linkRelations - key1 := relationKey{consumer: consumer1, target: event} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, event); exists == false { t.Error("First link should be stored in linkRelations") } - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Error("Second link should be stored in linkRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -295,7 +292,7 @@ func TestLinkEvent_Remote_SecondSubscriber_Buffered_SendsNetwork(t *testing.T) { } // allowAlwaysFirst still true! - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry.allowAlwaysFirst == false { t.Error("allowAlwaysFirst should stay true for buffered event") } @@ -318,17 +315,15 @@ func TestPublishEvent_Fanout(t *testing.T) { tm.LinkEvent(consumer2, event) // Verify both links stored - key1 := relationKey{consumer: consumer1, target: event} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, event); exists == false { t.Error("consumer1 link should be stored") } - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Error("consumer2 link should be stored") } // Verify subscriberCount - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry == nil { t.Fatal("Event entry should exist") } @@ -388,7 +383,7 @@ func TestPublishEvent_UpdatesBuffer(t *testing.T) { ) // Check buffer - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.buffer.len != 3 { t.Errorf("Buffer should have 3 messages, got %d", entry.buffer.len) } @@ -426,7 +421,7 @@ func TestPublishEvent_BufferOverflow(t *testing.T) { ) // Buffer should have 2 messages (msg2, msg3 - msg1 flushed) - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.buffer.len != 2 { t.Errorf("Buffer should have 2 messages, got %d", entry.buffer.len) } @@ -460,17 +455,15 @@ func TestUnregisterEvent_SendsExit(t *testing.T) { tm.LinkEvent(consumer2, event) // Verify links stored before unregister - key1 := relationKey{consumer: consumer1, target: event} - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, event); exists == false { t.Fatal("consumer1 link should exist before unregister") } - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Fatal("consumer2 link should exist before unregister") } // Verify producerEvents has producer - if _, exists := tm.producerEvents[producer]; exists == false { + if pe := tm.getProducerEventsMap(producer); pe == nil { t.Fatal("producerEvents should have producer before unregister") } @@ -490,20 +483,20 @@ func TestUnregisterEvent_SendsExit(t *testing.T) { } // Event removed - if _, exists := tm.events[event]; exists { + if entry := tm.getEventEntry(event); entry != nil { t.Error("Event should be removed") } // linkRelations cleaned - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, event); exists { t.Error("consumer1 link should be cleaned after unregister") } - if _, exists := tm.linkRelations[key2]; exists { + if exists := tm.hasLinkRelation(consumer2, event); exists { t.Error("consumer2 link should be cleaned after unregister") } // producerEvents cleaned - if _, exists := tm.producerEvents[producer]; exists { + if pe := tm.getProducerEventsMap(producer); pe != nil { t.Error("producerEvents should be cleaned after unregister") } } @@ -537,7 +530,7 @@ func TestMonitorEvent_Local_SharesCounter(t *testing.T) { } // Counter = 2 (link + monitor) - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 2 { t.Errorf("Counter should be 2 (link+monitor), got %d", entry.subscriberCount) } @@ -560,17 +553,15 @@ func TestUnlinkDemonitor_EventStop_WhenBothGone(t *testing.T) { tm.MonitorEvent(monitorConsumer, event) // Verify both relations exist - linkKey := relationKey{consumer: linkConsumer, target: event} - monitorKey := relationKey{consumer: monitorConsumer, target: event} - if _, exists := tm.linkRelations[linkKey]; exists == false { + if exists := tm.hasLinkRelation(linkConsumer, event); exists == false { t.Fatal("Link should exist") } - if _, exists := tm.monitorRelations[monitorKey]; exists == false { + if exists := tm.hasMonitorRelation(monitorConsumer, event); exists == false { t.Fatal("Monitor should exist") } // Verify subscriberCount = 2 - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 2 { t.Fatalf("subscriberCount should be 2, got %d", entry.subscriberCount) } @@ -587,10 +578,10 @@ func TestUnlinkDemonitor_EventStop_WhenBothGone(t *testing.T) { } // Verify link removed, monitor still exists - if _, exists := tm.linkRelations[linkKey]; exists { + if exists := tm.hasLinkRelation(linkConsumer, event); exists { t.Error("Link should be removed after unlink") } - if _, exists := tm.monitorRelations[monitorKey]; exists == false { + if exists := tm.hasMonitorRelation(monitorConsumer, event); exists == false { t.Error("Monitor should still exist") } @@ -609,10 +600,10 @@ func TestUnlinkDemonitor_EventStop_WhenBothGone(t *testing.T) { } // Verify both relations cleaned - if _, exists := tm.linkRelations[linkKey]; exists { + if exists := tm.hasLinkRelation(linkConsumer, event); exists { t.Error("Link should be removed") } - if _, exists := tm.monitorRelations[monitorKey]; exists { + if exists := tm.hasMonitorRelation(monitorConsumer, event); exists { t.Error("Monitor should be removed") } @@ -753,12 +744,10 @@ func TestUnlinkEvent_Remote_NotLast(t *testing.T) { tm.LinkEvent(consumer2, event) // Verify both stored - key1 := relationKey{consumer: consumer1, target: event} - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, event); exists == false { t.Fatal("consumer1 link should exist before unlink") } - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Fatal("consumer2 link should exist before unlink") } @@ -769,17 +758,17 @@ func TestUnlinkEvent_Remote_NotLast(t *testing.T) { } // Verify removed from linkRelations - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, event); exists { t.Error("consumer1 link should be removed") } // consumer2 still exists - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Error("consumer2 link should still exist") } // Verify targetIndex still exists with consumer2 - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should still exist") } @@ -808,12 +797,11 @@ func TestUnlinkEvent_Remote_LastLocal_SendsUnlink(t *testing.T) { } // Verify stored before unlink - key := relationKey{consumer: consumer, target: event} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, event); exists == false { t.Fatal("Link should exist before unlink") } - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should exist before unlink") } @@ -825,12 +813,12 @@ func TestUnlinkEvent_Remote_LastLocal_SendsUnlink(t *testing.T) { } // Verify removed from linkRelations - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, event); exists { t.Error("Link should be removed") } // Verify targetIndex cleaned (last consumer) - if _, exists := tm.targetIndex[event]; exists { + if entry := tm.getTargetEntry(event); entry != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -851,12 +839,10 @@ func TestDemonitorEvent_Remote_NotLast(t *testing.T) { tm.MonitorEvent(consumer2, event) // Verify both stored before demonitor - key1 := relationKey{consumer: consumer1, target: event} - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, event); exists == false { t.Fatal("consumer1 monitor should exist before demonitor") } - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, event); exists == false { t.Fatal("consumer2 monitor should exist before demonitor") } @@ -867,17 +853,17 @@ func TestDemonitorEvent_Remote_NotLast(t *testing.T) { } // consumer1 removed - if _, exists := tm.monitorRelations[key1]; exists { + if exists := tm.hasMonitorRelation(consumer1, event); exists { t.Error("consumer1 monitor should be removed") } // consumer2 still exists - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, event); exists == false { t.Error("consumer2 monitor should still exist") } // Verify targetIndex still exists with consumer2 - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should still exist") } @@ -900,12 +886,11 @@ func TestDemonitorEvent_Remote_LastLocal_SendsDemonitor(t *testing.T) { tm.MonitorEvent(consumer, event) // Verify stored before demonitor - key := relationKey{consumer: consumer, target: event} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, event); exists == false { t.Fatal("Monitor should exist before demonitor") } - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should exist before demonitor") } @@ -920,12 +905,12 @@ func TestDemonitorEvent_Remote_LastLocal_SendsDemonitor(t *testing.T) { } // Verify removed from monitorRelations - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, event); exists { t.Error("Monitor should be removed") } // Verify targetIndex cleaned (last consumer) - if _, exists := tm.targetIndex[event]; exists { + if entry := tm.getTargetEntry(event); entry != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -953,8 +938,7 @@ func TestUnlinkEvent_Remote_ConnectionError(t *testing.T) { } // Still cleaned locally - key := relationKey{consumer: consumer, target: event} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, event); exists { t.Error("Link should be cleaned even if connection fails") } } @@ -972,7 +956,7 @@ func TestMonitorEvent_Remote_Unbuffered_SecondNoNetwork(t *testing.T) { tm.MonitorEvent(consumer1, event) // allowAlwaysFirst should be false now (unbuffered) - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should exist") } @@ -991,13 +975,11 @@ func TestMonitorEvent_Remote_Unbuffered_SecondNoNetwork(t *testing.T) { } // Verify both stored locally - key1 := relationKey{consumer: consumer1, target: event} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, event); exists == false { t.Error("First monitor should exist") } - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, event); exists == false { t.Error("Second monitor should exist") } @@ -1033,18 +1015,16 @@ func TestMonitorEvent_Remote_Buffered_SecondGetsBuffer(t *testing.T) { } // Verify both monitors stored in monitorRelations - key1 := relationKey{consumer: consumer1, target: event} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, event); exists == false { t.Error("First monitor should be stored in monitorRelations") } - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, event); exists == false { t.Error("Second monitor should be stored in monitorRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[event] + entry := tm.getTargetEntry(event) if entry == nil { t.Fatal("targetIndex should exist") } diff --git a/node/tm/helpers_test.go b/node/tm/helpers_test.go new file mode 100644 index 000000000..3eba00673 --- /dev/null +++ b/node/tm/helpers_test.go @@ -0,0 +1,74 @@ +package tm + +import "ergo.services/ergo/gen" + +// Test helpers: aggregate views across shards + +func (tm *targetManager) totalLinks() int { + count := 0 + for i := range tm.shards { + count += len(tm.shards[i].linkRelations) + } + return count +} + +func (tm *targetManager) totalMonitors() int { + count := 0 + for i := range tm.shards { + count += len(tm.shards[i].monitorRelations) + } + return count +} + +func (tm *targetManager) totalEvents() int { + count := 0 + for i := range tm.shards { + count += len(tm.shards[i].events) + } + return count +} + +func (tm *targetManager) totalTargetIndex() int { + count := 0 + for i := range tm.shards { + count += len(tm.shards[i].targetIndex) + } + return count +} + +func (tm *targetManager) hasLinkRelation(consumer gen.PID, target any) bool { + s := tm.shardFor(target) + _, exists := s.linkRelations[relationKey{consumer: consumer, target: target}] + return exists +} + +func (tm *targetManager) hasMonitorRelation(consumer gen.PID, target any) bool { + s := tm.shardFor(target) + _, exists := s.monitorRelations[relationKey{consumer: consumer, target: target}] + return exists +} + +func (tm *targetManager) getTargetEntry(target any) *targetEntry { + s := tm.shardFor(target) + return s.targetIndex[target] +} + +func (tm *targetManager) getEventEntry(event gen.Event) *eventEntry { + s := tm.shardFor(event) + return s.events[event] +} + +func (tm *targetManager) getProducerEventsMap(producer gen.PID) map[gen.Event]struct{} { + result := make(map[gen.Event]struct{}) + for i := range tm.shards { + if pe := tm.shards[i].producerEvents[producer]; pe != nil { + for event := range pe { + result[event] = struct{}{} + } + } + } + if len(result) == 0 { + return nil + } + return result +} diff --git a/node/tm/manager.go b/node/tm/manager.go index c3679d770..5e9193949 100644 --- a/node/tm/manager.go +++ b/node/tm/manager.go @@ -3,24 +3,30 @@ package tm import ( "sync" "sync/atomic" + "time" "ergo.services/ergo/gen" ) -// targetManager implements gen.TargetManager interface -type targetManager struct { - mutex sync.RWMutex +const defaultNumShards = 16 - core gen.CoreTargetManager +type shard struct { + mutex sync.RWMutex - // Link/Monitor relationships linkRelations map[relationKey]struct{} monitorRelations map[relationKey]struct{} targetIndex map[any]*targetEntry - // Event storage + // Events that hash to this shard events map[gen.Event]*eventEntry - producerEvents map[gen.PID]map[gen.Event]struct{} // producer -> events index + producerEvents map[gen.PID]map[gen.Event]struct{} +} + +// targetManager implements gen.TargetManager interface +type targetManager struct { + core gen.CoreTargetManager + shards []shard + numShards uint64 // Statistics exitSignalsProduced atomic.Int64 @@ -53,15 +59,15 @@ type eventRingBuffer struct { } func (rb *eventRingBuffer) push(msg gen.MessageEvent) { - idx := (rb.head + rb.len) % rb.size - if rb.len < rb.size { - rb.data[idx] = msg - rb.len++ - } else { - // overwrite oldest + if rb.len >= rb.size { rb.data[rb.head] = msg rb.head = (rb.head + 1) % rb.size + return } + + idx := (rb.head + rb.len) % rb.size + rb.data[idx] = msg + rb.len++ } func (rb *eventRingBuffer) snapshot() []gen.MessageEvent { @@ -80,8 +86,9 @@ type eventEntry struct { token gen.Ref notify bool - // Ring buffer (nil if unbuffered, protected by mutex) - buffer *eventRingBuffer + // Ring buffer (nil if unbuffered, protected by bufferMutex) + bufferMutex sync.Mutex + buffer *eventRingBuffer // Subscribers (links and monitors separately) // Slice for fast iteration, map for O(1) lookup/delete @@ -102,33 +109,96 @@ type eventEntry struct { type Options struct{} func Create(core gen.CoreTargetManager, options Options) gen.TargetManager { + n := uint64(defaultNumShards) + tm := &targetManager{ - core: core, - linkRelations: make(map[relationKey]struct{}), - monitorRelations: make(map[relationKey]struct{}), - targetIndex: make(map[any]*targetEntry), - events: make(map[gen.Event]*eventEntry), - producerEvents: make(map[gen.PID]map[gen.Event]struct{}), + core: core, + shards: make([]shard, n), + numShards: n, + } + + for i := uint64(0); i < n; i++ { + tm.shards[i] = shard{ + linkRelations: make(map[relationKey]struct{}), + monitorRelations: make(map[relationKey]struct{}), + targetIndex: make(map[any]*targetEntry), + events: make(map[gen.Event]*eventEntry), + producerEvents: make(map[gen.PID]map[gen.Event]struct{}), + } } return tm } func (tm *targetManager) Info() gen.TargetManagerInfo { - tm.mutex.RLock() - defer tm.mutex.RUnlock() + var links, monitors, events int64 + + for i := range tm.shards { + s := &tm.shards[i] + s.mutex.RLock() + links += int64(len(s.linkRelations)) + monitors += int64(len(s.monitorRelations)) + events += int64(len(s.events)) + s.mutex.RUnlock() + } return gen.TargetManagerInfo{ - Links: int64(len(tm.linkRelations)), - Monitors: int64(len(tm.monitorRelations)), - Events: int64(len(tm.events)), + Links: links, + Monitors: monitors, + Events: events, ExitSignalsProduced: tm.exitSignalsProduced.Load(), ExitSignalsDelivered: tm.exitSignalsDelivered.Load(), DownMessagesProduced: tm.downMessagesProduced.Load(), DownMessagesDelivered: tm.downMessagesDelivered.Load(), EventsPublished: tm.eventsPublished.Load(), - EventsReceived: tm.eventsReceived.Load(), - EventsLocalSent: tm.eventsLocalSent.Load(), - EventsRemoteSent: tm.eventsRemoteSent.Load(), + EventsReceived: tm.eventsReceived.Load(), + EventsLocalSent: tm.eventsLocalSent.Load(), + EventsRemoteSent: tm.eventsRemoteSent.Load(), + } +} + +// shardFor returns the shard responsible for the given target. +// Uses bit masking (numShards must be power of 2). +func (tm *targetManager) shardFor(target any) *shard { + var idx uint64 + switch t := target.(type) { + case gen.PID: + idx = t.ID + case gen.Alias: + idx = t.ID[1] + case gen.ProcessID: + idx = fnv1aString(string(t.Name)) + case gen.Event: + idx = fnv1aString(string(t.Name)) + case gen.Atom: + idx = fnv1aString(string(t)) + } + return &tm.shards[idx&(tm.numShards-1)] +} + +// fnv1aString is an inline FNV-1a hash for strings (no allocation). +func fnv1aString(s string) uint64 { + h := uint64(14695981039346656037) + for i := 0; i < len(s); i++ { + h ^= uint64(s[i]) + h *= 1099511628211 + } + return h +} + +// getEventBuffer returns a snapshot of the event buffer, or nil. +func getEventBuffer(entry *eventEntry) []gen.MessageEvent { + if entry.buffer == nil { + return nil + } + return entry.buffer.snapshot() +} + +// generateToken creates a unique event token. +func (tm *targetManager) generateToken() gen.Ref { + return gen.Ref{ + Node: tm.core.Name(), + Creation: tm.core.PID().Creation, + ID: [3]uint64{uint64(time.Now().UnixNano()), 0, 0}, } } diff --git a/node/tm/node.go b/node/tm/node.go index aadadea26..808d597dd 100644 --- a/node/tm/node.go +++ b/node/tm/node.go @@ -5,28 +5,27 @@ import "ergo.services/ergo/gen" // Node operations (always local - connection monitoring) func (tm *targetManager) LinkNode(consumer gen.PID, target gen.Atom) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists { + if _, exists := s.linkRelations[key]; exists { return gen.ErrTargetExist } - // Add to linkRelations - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} - // Add to targetIndex - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { entry = &targetEntry{ consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry } entry.consumers[consumer] = struct{}{} @@ -34,55 +33,56 @@ func (tm *targetManager) LinkNode(consumer gen.PID, target gen.Atom) error { } func (tm *targetManager) UnlinkNode(consumer gen.PID, target gen.Atom) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists == false { + if _, exists := s.linkRelations[key]; exists == false { return nil } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - entry := tm.targetIndex[target] - if entry != nil { - delete(entry.consumers, consumer) + entry := s.targetIndex[target] + if entry == nil { + return nil + } - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) - } + delete(entry.consumers, consumer) + if len(entry.consumers) == 0 { + delete(s.targetIndex, target) } return nil } func (tm *targetManager) MonitorNode(consumer gen.PID, target gen.Atom) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists { + if _, exists := s.monitorRelations[key]; exists { return gen.ErrTargetExist } - // Add to monitorRelations (always local - no remote for Node targets) - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} - // Add to targetIndex - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { entry = &targetEntry{ consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry } entry.consumers[consumer] = struct{}{} @@ -90,27 +90,29 @@ func (tm *targetManager) MonitorNode(consumer gen.PID, target gen.Atom) error { } func (tm *targetManager) DemonitorNode(consumer gen.PID, target gen.Atom) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return nil } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[target] - if entry != nil { - delete(entry.consumers, consumer) + entry := s.targetIndex[target] + if entry == nil { + return nil + } - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) - } + delete(entry.consumers, consumer) + if len(entry.consumers) == 0 { + delete(s.targetIndex, target) } return nil diff --git a/node/tm/node_test.go b/node/tm/node_test.go index a8da80a28..dafa845fd 100644 --- a/node/tm/node_test.go +++ b/node/tm/node_test.go @@ -21,13 +21,12 @@ func TestLinkNode_Basic(t *testing.T) { } // Stored - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Node link should be stored") } // Verify in targetIndex - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetEntry should be created") } @@ -52,24 +51,17 @@ func TestLinkNode_Duplicate_Error(t *testing.T) { } // Verify first link still stored (not corrupted by duplicate attempt) - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Original link should still be stored") } - // Verify only 1 link in linkRelations for this consumer - count := 0 - for k := range tm.linkRelations { - if k.consumer == consumer { - count++ - } - } - if count != 1 { - t.Errorf("Expected 1 link for consumer, got %d", count) + // Verify only 1 link total (duplicate was rejected) + if tm.totalLinks() != 1 { + t.Errorf("Expected 1 link total, got %d", tm.totalLinks()) } // Verify targetIndex has exactly 1 consumer - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should exist") } @@ -103,7 +95,7 @@ func TestLinkNode_MultipleConsumers(t *testing.T) { } // Verify targetIndex has all consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if len(entry.consumers) != 3 { t.Errorf("Expected 3 consumers, got %d", len(entry.consumers)) } @@ -126,13 +118,12 @@ func TestUnlinkNode_Basic(t *testing.T) { } // Removed - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Node link should be removed") } // targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned") } } @@ -151,19 +142,17 @@ func TestUnlinkNode_NotLast(t *testing.T) { tm.UnlinkNode(consumer1, target) // consumer1 removed - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, target); exists { t.Error("consumer1 link should be removed") } // consumer2 still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, target); exists == false { t.Error("consumer2 link should still exist") } // targetIndex still exists with consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should still exist") } @@ -203,13 +192,12 @@ func TestMonitorNode_Basic(t *testing.T) { } // Stored in monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Node monitor should be stored") } // Verify in targetIndex - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetEntry should be created") } @@ -238,24 +226,17 @@ func TestMonitorNode_Duplicate_Error(t *testing.T) { } // Verify first monitor still stored (not corrupted by duplicate attempt) - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Original monitor should still be stored") } - // Verify only 1 monitor in monitorRelations for this consumer - count := 0 - for k := range tm.monitorRelations { - if k.consumer == consumer { - count++ - } - } - if count != 1 { - t.Errorf("Expected 1 monitor for consumer, got %d", count) + // Verify only 1 monitor total (duplicate was rejected) + if tm.totalMonitors() != 1 { + t.Errorf("Expected 1 monitor total, got %d", tm.totalMonitors()) } // Verify targetIndex has exactly 1 consumer - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should exist") } @@ -284,17 +265,15 @@ func TestMonitorNode_MultipleConsumers(t *testing.T) { } // Verify both stored in monitorRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, target); exists == false { t.Error("consumer1 should be in monitorRelations") } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 should be in monitorRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should exist") } @@ -320,13 +299,12 @@ func TestDemonitorNode_Basic(t *testing.T) { } // Removed - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Node monitor should be removed") } // targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned") } } @@ -345,19 +323,17 @@ func TestDemonitorNode_NotLast(t *testing.T) { tm.DemonitorNode(consumer1, target) // consumer1 removed - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists { + if exists := tm.hasMonitorRelation(consumer1, target); exists { t.Error("consumer1 monitor should be removed") } // consumer2 still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 monitor should still exist") } // targetIndex still exists with consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should still exist") } diff --git a/node/tm/pid.go b/node/tm/pid.go index 5a6f16edf..404dae880 100644 --- a/node/tm/pid.go +++ b/node/tm/pid.go @@ -3,137 +3,108 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) LinkPID(consumer gen.PID, target gen.PID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - // Check if already exists - if _, exists := tm.linkRelations[key]; exists { - // Special case: remote PID linking to local target (concurrent CorePID) - if consumer.Node != tm.core.Name() { - // Remote consumer - ignore duplicate (CorePID optimization) - return nil - } - + _, exists := s.linkRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - // Add to linkRelations - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} - // Check targetIndex for remote request decision - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { - // First subscriber overall - create entry entry = &targetEntry{ allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } - // Check if allowAlwaysFirst permits remote request if entry.allowAlwaysFirst == true { needsRemote = true } - // Add consumer to entry entry.consumers[consumer] = struct{}{} - // Check if target is local if target.Node == tm.core.Name() { - // Local target - no remote request needed return nil } - // Remote target if needsRemote == false { - // Not allowed to send remote (someone already succeeded) return nil } - // Send remote LinkPID with CorePID connection, err := tm.core.GetConnection(target.Node) if err != nil { - // Network error - rollback - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.LinkPID(tm.core.PID(), target) if err != nil { - // Remote LinkPID failed - rollback - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } - // Success! Set allowAlwaysFirst=false to prevent future remote requests entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) UnlinkPID(consumer gen.PID, target gen.PID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - // Check if exists - if _, exists := tm.linkRelations[key]; exists == false { - // Idempotent - not an error if already removed + if _, exists := s.linkRelations[key]; exists == false { return nil } - // Remove from linkRelations - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - // Remove from targetIndex - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } delete(entry.consumers, consumer) - // Check if last consumer isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - // Check if target is local if target.Node == tm.core.Name() { - // Local target - no remote request needed return nil } - // Remote target - check if last LOCAL consumer if isLast == false { - // Other consumers still exist - check if any are local hasLocal := false for pid := range entry.consumers { if pid.Node == tm.core.Name() && pid != tm.core.PID() { @@ -141,51 +112,41 @@ func (tm *targetManager) UnlinkPID(consumer gen.PID, target gen.PID) error { break } } - if hasLocal { - // Other local consumers exist - don't send UnlinkPID return nil } } - // Last local consumer (or isLast overall) - send remote UnlinkPID connection, err := tm.core.GetConnection(target.Node) if err != nil { - // Connection lost - not an error, remote will cleanup via RouteNodeDown return nil } - // Send UnlinkPID with CorePID (ignore errors - best effort) connection.UnlinkPID(tm.core.PID(), target) - return nil } func (tm *targetManager) MonitorPID(consumer gen.PID, target gen.PID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - // Check if already exists - if _, exists := tm.monitorRelations[key]; exists { - // Special case: remote PID monitoring local target - if consumer.Node != tm.core.Name() { - // Remote consumer - ignore duplicate - return nil - } - + _, exists := s.monitorRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - // Add to monitorRelations - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} - // Check targetIndex for remote request decision - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { @@ -193,7 +154,7 @@ func (tm *targetManager) MonitorPID(consumer gen.PID, target gen.PID) error { allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } @@ -203,65 +164,55 @@ func (tm *targetManager) MonitorPID(consumer gen.PID, target gen.PID) error { entry.consumers[consumer] = struct{}{} - // Check if target is local if target.Node == tm.core.Name() { return nil } - // Remote target if needsRemote == false { return nil } - // Send remote MonitorPID connection, err := tm.core.GetConnection(target.Node) if err != nil { - // Rollback - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.MonitorPID(tm.core.PID(), target) if err != nil { - // Rollback - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } - // Success entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) DemonitorPID(consumer gen.PID, target gen.PID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return nil } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } @@ -269,9 +220,8 @@ func (tm *targetManager) DemonitorPID(consumer gen.PID, target gen.PID) error { delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } if target.Node == tm.core.Name() { @@ -286,7 +236,6 @@ func (tm *targetManager) DemonitorPID(consumer gen.PID, target gen.PID) error { break } } - if hasLocal { return nil } @@ -298,6 +247,5 @@ func (tm *targetManager) DemonitorPID(consumer gen.PID, target gen.PID) error { } connection.DemonitorPID(tm.core.PID(), target) - return nil } diff --git a/node/tm/pid_test.go b/node/tm/pid_test.go index 5873f0267..7f8a63e70 100644 --- a/node/tm/pid_test.go +++ b/node/tm/pid_test.go @@ -20,12 +20,11 @@ func TestLinkPID_Local_Basic(t *testing.T) { t.Fatalf("LinkPID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if tm.hasLinkRelation(consumer, target) == false { t.Error("Link should be stored in linkRelations") } - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetEntry should be created") } @@ -51,8 +50,7 @@ func TestLinkPID_Remote_FirstSubscriber(t *testing.T) { t.Fatalf("LinkPID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if tm.hasLinkRelation(consumer, target) == false { t.Error("Link should be stored locally") } @@ -71,7 +69,7 @@ func TestLinkPID_Remote_FirstSubscriber(t *testing.T) { } } - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry.allowAlwaysFirst == true { t.Error("allowAlwaysFirst should be false after successful remote link") } @@ -101,8 +99,7 @@ func TestLinkPID_Remote_SecondSubscriber_NoNetwork(t *testing.T) { t.Fatalf("Second LinkPID failed: %v", err) } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if tm.hasLinkRelation(consumer2, target) == false { t.Error("Second link should be stored locally") } @@ -110,7 +107,7 @@ func TestLinkPID_Remote_SecondSubscriber_NoNetwork(t *testing.T) { t.Errorf("Second subscriber should NOT send network request (CorePID optimization), got %d", core.countSentLinks()) } - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if len(entry.consumers) != 2 { t.Errorf("Expected 2 consumers in targetIndex, got %d", len(entry.consumers)) } @@ -133,8 +130,8 @@ func TestLinkPID_Remote_ThreeSubscribers_OneNetworkRequest(t *testing.T) { t.Errorf("Expected exactly 1 network request for 3 subscribers, got %d", core.countSentLinks()) } - if len(tm.linkRelations) != 3 { - t.Errorf("Expected 3 links stored locally, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 3 { + t.Errorf("Expected 3 links stored locally, got %d", tm.totalLinks()) } if sent, ok := core.getFirstSentLink(); ok { @@ -177,12 +174,11 @@ func TestLinkPID_NetworkError_Rollback(t *testing.T) { t.Errorf("Expected ErrNoConnection, got %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if tm.hasLinkRelation(consumer, target) { t.Error("Link should be rolled back after network error") } - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -202,8 +198,7 @@ func TestLinkPID_RemoteError_Rollback(t *testing.T) { t.Errorf("Expected ErrProcessUnknown, got %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if tm.hasLinkRelation(consumer, target) { t.Error("Link should be rolled back after remote error") } } @@ -226,12 +221,12 @@ func TestLinkPID_RemoteCorePID_Duplicate_Ignored(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored, not added twice) - if len(tm.linkRelations) != 1 { - t.Errorf("Expected 1 link relation, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1 { + t.Errorf("Expected 1 link relation, got %d", tm.totalLinks()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -261,19 +256,17 @@ func TestUnlinkPID_NotLastLocal(t *testing.T) { } // Verify consumer1 link removed from linkRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists { + if tm.hasLinkRelation(consumer1, target) { t.Error("consumer1 link should be removed from linkRelations") } // Verify consumer2 link still exists in linkRelations - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if tm.hasLinkRelation(consumer2, target) == false { t.Error("consumer2 link should still exist in linkRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } @@ -306,12 +299,11 @@ func TestUnlinkPID_LastLocal_SendsUnlink(t *testing.T) { t.Fatalf("UnlinkPID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if tm.hasLinkRelation(consumer, target) { t.Error("Link should be removed") } - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -344,8 +336,7 @@ func TestMonitorPID_Local_Basic(t *testing.T) { t.Fatalf("MonitorPID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if tm.hasMonitorRelation(consumer, target) == false { t.Error("Monitor should be stored") } @@ -411,12 +402,12 @@ func TestMonitorPID_Remote_ThreeSubscribers(t *testing.T) { } // Verify all 3 monitors stored in monitorRelations - if len(tm.monitorRelations) != 3 { - t.Errorf("Expected 3 monitor relations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 3 { + t.Errorf("Expected 3 monitor relations, got %d", tm.totalMonitors()) } // Verify targetIndex has all 3 consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -462,8 +453,7 @@ func TestMonitorPID_NetworkError_Rollback(t *testing.T) { t.Errorf("Expected ErrNoConnection, got %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if tm.hasMonitorRelation(consumer, target) { t.Error("Monitor should be rolled back") } } @@ -483,8 +473,7 @@ func TestMonitorPID_RemoteError_Rollback(t *testing.T) { t.Errorf("Expected ErrProcessUnknown, got %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if tm.hasMonitorRelation(consumer, target) { t.Error("Monitor should be rolled back") } } @@ -507,12 +496,12 @@ func TestMonitorPID_RemoteCorePID_Duplicate(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored, not added twice) - if len(tm.monitorRelations) != 1 { - t.Errorf("Expected 1 monitor relation, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 1 { + t.Errorf("Expected 1 monitor relation, got %d", tm.totalMonitors()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -535,8 +524,7 @@ func TestMonitorPID_ReSubscribe(t *testing.T) { } // Verify monitor stored - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if tm.hasMonitorRelation(consumer, target) == false { t.Error("Monitor should be stored after first MonitorPID") } @@ -545,10 +533,10 @@ func TestMonitorPID_ReSubscribe(t *testing.T) { tm.DemonitorPID(consumer, target) // Verify monitor removed after demonitor - if _, exists := tm.monitorRelations[key]; exists { + if tm.hasMonitorRelation(consumer, target) { t.Error("Monitor should be removed after DemonitorPID") } - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned after DemonitorPID") } @@ -563,12 +551,12 @@ func TestMonitorPID_ReSubscribe(t *testing.T) { } // Verify monitor stored again - if _, exists := tm.monitorRelations[key]; exists == false { + if tm.hasMonitorRelation(consumer, target) == false { t.Error("Monitor should be stored after re-subscribe") } // Verify targetIndex recreated - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should be recreated after re-subscribe") } @@ -595,19 +583,17 @@ func TestDemonitorPID_NotLast(t *testing.T) { tm.DemonitorPID(consumer1, target) // Verify consumer1 monitor removed from monitorRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists { + if tm.hasMonitorRelation(consumer1, target) { t.Error("consumer1 monitor should be removed from monitorRelations") } // Verify consumer2 monitor still exists in monitorRelations - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if tm.hasMonitorRelation(consumer2, target) == false { t.Error("consumer2 monitor should still exist in monitorRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } diff --git a/node/tm/process_id.go b/node/tm/process_id.go index e766ecd86..a05537d28 100644 --- a/node/tm/process_id.go +++ b/node/tm/process_id.go @@ -3,25 +3,26 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) LinkProcessID(consumer gen.PID, target gen.ProcessID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists { - if consumer.Node != tm.core.Name() { - return nil - } - + _, exists := s.linkRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - tm.linkRelations[key] = struct{}{} + s.linkRelations[key] = struct{}{} - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { @@ -29,7 +30,7 @@ func (tm *targetManager) LinkProcessID(consumer gen.PID, target gen.ProcessID) e allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } @@ -39,7 +40,6 @@ func (tm *targetManager) LinkProcessID(consumer gen.PID, target gen.ProcessID) e entry.consumers[consumer] = struct{}{} - // Check if target is local targetNode := target.Node if targetNode == "" { targetNode = tm.core.Name() @@ -55,49 +55,45 @@ func (tm *targetManager) LinkProcessID(consumer gen.PID, target gen.ProcessID) e connection, err := tm.core.GetConnection(targetNode) if err != nil { - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.LinkProcessID(tm.core.PID(), target) if err != nil { - delete(tm.linkRelations, key) + delete(s.linkRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) UnlinkProcessID(consumer gen.PID, target gen.ProcessID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.linkRelations[key]; exists == false { + if _, exists := s.linkRelations[key]; exists == false { return nil } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } @@ -105,9 +101,8 @@ func (tm *targetManager) UnlinkProcessID(consumer gen.PID, target gen.ProcessID) delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } targetNode := target.Node @@ -127,7 +122,6 @@ func (tm *targetManager) UnlinkProcessID(consumer gen.PID, target gen.ProcessID) break } } - if hasLocal { return nil } @@ -139,30 +133,30 @@ func (tm *targetManager) UnlinkProcessID(consumer gen.PID, target gen.ProcessID) } connection.UnlinkProcessID(tm.core.PID(), target) - return nil } func (tm *targetManager) MonitorProcessID(consumer gen.PID, target gen.ProcessID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists { - if consumer.Node != tm.core.Name() { - return nil - } - + _, exists := s.monitorRelations[key] + if exists == true && consumer.Node != tm.core.Name() { + return nil + } + if exists == true { return gen.ErrTargetExist } - tm.monitorRelations[key] = struct{}{} + s.monitorRelations[key] = struct{}{} - entry := tm.targetIndex[target] + entry := s.targetIndex[target] needsRemote := false if entry == nil { @@ -170,7 +164,7 @@ func (tm *targetManager) MonitorProcessID(consumer gen.PID, target gen.ProcessID allowAlwaysFirst: true, consumers: make(map[gen.PID]struct{}), } - tm.targetIndex[target] = entry + s.targetIndex[target] = entry needsRemote = true } @@ -195,49 +189,45 @@ func (tm *targetManager) MonitorProcessID(consumer gen.PID, target gen.ProcessID connection, err := tm.core.GetConnection(targetNode) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } err = connection.MonitorProcessID(tm.core.PID(), target) if err != nil { - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) delete(entry.consumers, consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } - return err } entry.allowAlwaysFirst = false - return nil } func (tm *targetManager) DemonitorProcessID(consumer gen.PID, target gen.ProcessID) error { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(target) + s.mutex.Lock() + defer s.mutex.Unlock() key := relationKey{ consumer: consumer, target: target, } - if _, exists := tm.monitorRelations[key]; exists == false { + if _, exists := s.monitorRelations[key]; exists == false { return nil } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[target] + entry := s.targetIndex[target] if entry == nil { return nil } @@ -245,9 +235,8 @@ func (tm *targetManager) DemonitorProcessID(consumer gen.PID, target gen.Process delete(entry.consumers, consumer) isLast := (len(entry.consumers) == 0) - if isLast { - delete(tm.targetIndex, target) + delete(s.targetIndex, target) } targetNode := target.Node @@ -267,7 +256,6 @@ func (tm *targetManager) DemonitorProcessID(consumer gen.PID, target gen.Process break } } - if hasLocal { return nil } @@ -279,6 +267,5 @@ func (tm *targetManager) DemonitorProcessID(consumer gen.PID, target gen.Process } connection.DemonitorProcessID(tm.core.PID(), target) - return nil } diff --git a/node/tm/process_id_test.go b/node/tm/process_id_test.go index d49e20164..b492a1cc6 100644 --- a/node/tm/process_id_test.go +++ b/node/tm/process_id_test.go @@ -20,8 +20,7 @@ func TestLinkProcessID_Local(t *testing.T) { t.Fatalf("LinkProcessID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should be stored") } @@ -42,8 +41,7 @@ func TestLinkProcessID_Local_EmptyNode(t *testing.T) { t.Fatalf("LinkProcessID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should be stored") } @@ -65,13 +63,12 @@ func TestLinkProcessID_Remote_First(t *testing.T) { } // Verify link stored in linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should be stored in linkRelations") } // Verify targetIndex created - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should be created") } @@ -114,20 +111,18 @@ func TestLinkProcessID_Remote_Second(t *testing.T) { } // Verify both links stored in linkRelations - if len(tm.linkRelations) != 2 { - t.Errorf("Expected 2 link relations, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 2 { + t.Errorf("Expected 2 link relations, got %d", tm.totalLinks()) } - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists == false { + if exists := tm.hasLinkRelation(consumer1, target); exists == false { t.Error("consumer1 link should exist in linkRelations") } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, target); exists == false { t.Error("consumer2 link should exist in linkRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -167,13 +162,12 @@ func TestLinkProcessID_NetworkError_Rollback(t *testing.T) { } // Verify link rolled back from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be rolled back from linkRelations") } // Verify targetIndex cleaned after rollback - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -196,12 +190,12 @@ func TestLinkProcessID_RemoteCorePID_Duplicate_Ignored(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored) - if len(tm.linkRelations) != 1 { - t.Errorf("Expected 1 link relation, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1 { + t.Errorf("Expected 1 link relation, got %d", tm.totalLinks()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -226,12 +220,11 @@ func TestUnlinkProcessID_Local(t *testing.T) { t.Fatalf("UnlinkProcessID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed") } - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -252,19 +245,17 @@ func TestUnlinkProcessID_NotLast(t *testing.T) { tm.UnlinkProcessID(consumer1, target) // Verify consumer1 link removed from linkRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, target); exists { t.Error("consumer1 link should be removed from linkRelations") } // Verify consumer2 link still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, target); exists == false { t.Error("consumer2 link should still exist in linkRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } @@ -297,13 +288,12 @@ func TestUnlinkProcessID_Last_SendsUnlink(t *testing.T) { } // Verify link removed from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed from linkRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned when last consumer removed") } @@ -340,8 +330,7 @@ func TestMonitorProcessID_Local(t *testing.T) { t.Fatalf("MonitorProcessID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should be stored") } @@ -363,8 +352,7 @@ func TestMonitorProcessID_Local_EmptyNode(t *testing.T) { } // Verify monitor stored in monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should be stored in monitorRelations") } @@ -387,13 +375,12 @@ func TestMonitorProcessID_Remote_First(t *testing.T) { } // Verify monitor stored in monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should be stored in monitorRelations") } // Verify targetIndex created - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should be created") } @@ -429,20 +416,18 @@ func TestMonitorProcessID_Remote_Second(t *testing.T) { } // Verify both monitors stored in monitorRelations - if len(tm.monitorRelations) != 2 { - t.Errorf("Expected 2 monitor relations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 2 { + t.Errorf("Expected 2 monitor relations, got %d", tm.totalMonitors()) } - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, target); exists == false { t.Error("consumer1 monitor should exist in monitorRelations") } - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 monitor should exist in monitorRelations") } // Verify targetIndex has both consumers - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -482,13 +467,12 @@ func TestMonitorProcessID_NetworkError_Rollback(t *testing.T) { } // Verify monitor rolled back from monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be rolled back from monitorRelations") } // Verify targetIndex cleaned after rollback - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -511,12 +495,12 @@ func TestMonitorProcessID_RemoteCorePID_Duplicate_Ignored(t *testing.T) { } // Verify only ONE relation exists (duplicate was ignored) - if len(tm.monitorRelations) != 1 { - t.Errorf("Expected 1 monitor relation, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 1 { + t.Errorf("Expected 1 monitor relation, got %d", tm.totalMonitors()) } // Verify targetIndex has only one consumer - entry := tm.targetIndex[localTarget] + entry := tm.getTargetEntry(localTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -541,12 +525,11 @@ func TestDemonitorProcessID_Local(t *testing.T) { t.Fatalf("DemonitorProcessID failed: %v", err) } - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be removed") } - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -567,19 +550,17 @@ func TestDemonitorProcessID_NotLast(t *testing.T) { tm.DemonitorProcessID(consumer1, target) // Verify consumer1 monitor removed from monitorRelations - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.monitorRelations[key1]; exists { + if exists := tm.hasMonitorRelation(consumer1, target); exists { t.Error("consumer1 monitor should be removed from monitorRelations") } // Verify consumer2 monitor still exists - key2 := relationKey{consumer: consumer2, target: target} - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, target); exists == false { t.Error("consumer2 monitor should still exist in monitorRelations") } // Verify targetIndex still exists with only consumer2 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex entry should still exist") } @@ -612,13 +593,12 @@ func TestDemonitorProcessID_Last_SendsDemonitor(t *testing.T) { } // Verify monitor removed from monitorRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be removed from monitorRelations") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned when last consumer removed") } diff --git a/node/tm/query.go b/node/tm/query.go index 13c0e6443..d643d8648 100644 --- a/node/tm/query.go +++ b/node/tm/query.go @@ -3,75 +3,84 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) HasLink(consumer gen.PID, target any) bool { - tm.mutex.RLock() - defer tm.mutex.RUnlock() + s := tm.shardFor(target) + s.mutex.RLock() + defer s.mutex.RUnlock() key := relationKey{ consumer: consumer, target: target, } - _, exists := tm.linkRelations[key] + _, exists := s.linkRelations[key] return exists } func (tm *targetManager) HasMonitor(consumer gen.PID, target any) bool { - tm.mutex.RLock() - defer tm.mutex.RUnlock() + s := tm.shardFor(target) + s.mutex.RLock() + defer s.mutex.RUnlock() key := relationKey{ consumer: consumer, target: target, } - _, exists := tm.monitorRelations[key] + _, exists := s.monitorRelations[key] return exists } func (tm *targetManager) LinksFor(consumer gen.PID) []any { - tm.mutex.RLock() - defer tm.mutex.RUnlock() - var targets []any - for key := range tm.linkRelations { - if key.consumer == consumer { - targets = append(targets, key.target) + for i := range tm.shards { + s := &tm.shards[i] + s.mutex.RLock() + for key := range s.linkRelations { + if key.consumer == consumer { + targets = append(targets, key.target) + } } + s.mutex.RUnlock() } return targets } func (tm *targetManager) MonitorsFor(consumer gen.PID) []any { - tm.mutex.RLock() - defer tm.mutex.RUnlock() - var targets []any - for key := range tm.monitorRelations { - if key.consumer == consumer { - targets = append(targets, key.target) + for i := range tm.shards { + s := &tm.shards[i] + s.mutex.RLock() + for key := range s.monitorRelations { + if key.consumer == consumer { + targets = append(targets, key.target) + } } + s.mutex.RUnlock() } return targets } func (tm *targetManager) EventsFor(producer gen.PID) []gen.Event { - tm.mutex.RLock() - defer tm.mutex.RUnlock() - - // Use producerEvents index for O(1) lookup - eventSet := tm.producerEvents[producer] - if eventSet == nil { - return nil + var events []gen.Event + + for i := range tm.shards { + s := &tm.shards[i] + s.mutex.RLock() + pe := s.producerEvents[producer] + if pe != nil { + for event := range pe { + events = append(events, event) + } + } + s.mutex.RUnlock() } - events := make([]gen.Event, 0, len(eventSet)) - for event := range eventSet { - events = append(events, event) + if len(events) == 0 { + return nil } - return events } diff --git a/node/tm/query_test.go b/node/tm/query_test.go index efe9ada11..cdab4985e 100644 --- a/node/tm/query_test.go +++ b/node/tm/query_test.go @@ -68,26 +68,21 @@ func TestHasLink_DifferentTargetTypes(t *testing.T) { } // Verify internal state: all 4 relations stored - if len(tm.linkRelations) != 4 { - t.Errorf("expected 4 linkRelations, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 4 { + t.Errorf("expected 4 linkRelations, got %d", tm.totalLinks()) } // Verify each relation in linkRelations - keyPID := relationKey{consumer: consumer, target: targetPID} - keyProcessID := relationKey{consumer: consumer, target: targetProcessID} - keyAlias := relationKey{consumer: consumer, target: targetAlias} - keyNode := relationKey{consumer: consumer, target: targetNode} - - if _, exists := tm.linkRelations[keyPID]; exists == false { + if exists := tm.hasLinkRelation(consumer, targetPID); exists == false { t.Error("linkRelations should contain PID relation") } - if _, exists := tm.linkRelations[keyProcessID]; exists == false { + if exists := tm.hasLinkRelation(consumer, targetProcessID); exists == false { t.Error("linkRelations should contain ProcessID relation") } - if _, exists := tm.linkRelations[keyAlias]; exists == false { + if exists := tm.hasLinkRelation(consumer, targetAlias); exists == false { t.Error("linkRelations should contain Alias relation") } - if _, exists := tm.linkRelations[keyNode]; exists == false { + if exists := tm.hasLinkRelation(consumer, targetNode); exists == false { t.Error("linkRelations should contain Node relation") } } @@ -173,26 +168,21 @@ func TestHasMonitor_DifferentTargetTypes(t *testing.T) { } // Verify internal state: all 4 relations stored - if len(tm.monitorRelations) != 4 { - t.Errorf("expected 4 monitorRelations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 4 { + t.Errorf("expected 4 monitorRelations, got %d", tm.totalMonitors()) } // Verify each relation in monitorRelations - keyPID := relationKey{consumer: consumer, target: targetPID} - keyProcessID := relationKey{consumer: consumer, target: targetProcessID} - keyAlias := relationKey{consumer: consumer, target: targetAlias} - keyNode := relationKey{consumer: consumer, target: targetNode} - - if _, exists := tm.monitorRelations[keyPID]; exists == false { + if exists := tm.hasMonitorRelation(consumer, targetPID); exists == false { t.Error("monitorRelations should contain PID relation") } - if _, exists := tm.monitorRelations[keyProcessID]; exists == false { + if exists := tm.hasMonitorRelation(consumer, targetProcessID); exists == false { t.Error("monitorRelations should contain ProcessID relation") } - if _, exists := tm.monitorRelations[keyAlias]; exists == false { + if exists := tm.hasMonitorRelation(consumer, targetAlias); exists == false { t.Error("monitorRelations should contain Alias relation") } - if _, exists := tm.monitorRelations[keyNode]; exists == false { + if exists := tm.hasMonitorRelation(consumer, targetNode); exists == false { t.Error("monitorRelations should contain Node relation") } } @@ -323,19 +313,18 @@ func TestLinksFor_AfterRemovingOne(t *testing.T) { } // Verify internal state: target2 relation removed - key2 := relationKey{consumer: consumer, target: target2} - if _, exists := tm.linkRelations[key2]; exists { + if exists := tm.hasLinkRelation(consumer, target2); exists { t.Error("linkRelations should not contain removed target2") } // Verify targetIndex for target2 is cleaned - if _, exists := tm.targetIndex[target2]; exists { + if entry := tm.getTargetEntry(target2); entry != nil { t.Error("targetIndex for target2 should be cleaned") } // Verify remaining relations still exist - if len(tm.linkRelations) != 2 { - t.Errorf("expected 2 linkRelations remaining, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 2 { + t.Errorf("expected 2 linkRelations remaining, got %d", tm.totalLinks()) } } @@ -361,15 +350,15 @@ func TestLinksFor_AfterRemovingAll(t *testing.T) { } // Verify internal state: all linkRelations cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("expected 0 linkRelations, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("expected 0 linkRelations, got %d", tm.totalLinks()) } // Verify all targetIndex entries cleaned - if _, exists := tm.targetIndex[target1]; exists { + if entry := tm.getTargetEntry(target1); entry != nil { t.Error("targetIndex for target1 should be cleaned") } - if _, exists := tm.targetIndex[target2]; exists { + if entry := tm.getTargetEntry(target2); entry != nil { t.Error("targetIndex for target2 should be cleaned") } } @@ -439,12 +428,12 @@ func TestLinksFor_RemoteTargets(t *testing.T) { } // Verify internal state: both relations stored - if len(tm.linkRelations) != 2 { - t.Errorf("expected 2 linkRelations, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 2 { + t.Errorf("expected 2 linkRelations, got %d", tm.totalLinks()) } // Verify targetIndex for remote target has consumer - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex for remoteTarget should exist") } @@ -560,19 +549,18 @@ func TestMonitorsFor_AfterRemovingOne(t *testing.T) { } // Verify internal state: target2 relation removed - key2 := relationKey{consumer: consumer, target: target2} - if _, exists := tm.monitorRelations[key2]; exists { + if exists := tm.hasMonitorRelation(consumer, target2); exists { t.Error("monitorRelations should not contain removed target2") } // Verify targetIndex for target2 is cleaned - if _, exists := tm.targetIndex[target2]; exists { + if entry := tm.getTargetEntry(target2); entry != nil { t.Error("targetIndex for target2 should be cleaned") } // Verify remaining relations still exist - if len(tm.monitorRelations) != 2 { - t.Errorf("expected 2 monitorRelations remaining, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 2 { + t.Errorf("expected 2 monitorRelations remaining, got %d", tm.totalMonitors()) } } @@ -598,15 +586,15 @@ func TestMonitorsFor_AfterRemovingAll(t *testing.T) { } // Verify internal state: all monitorRelations cleaned - if len(tm.monitorRelations) != 0 { - t.Errorf("expected 0 monitorRelations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("expected 0 monitorRelations, got %d", tm.totalMonitors()) } // Verify all targetIndex entries cleaned - if _, exists := tm.targetIndex[target1]; exists { + if entry := tm.getTargetEntry(target1); entry != nil { t.Error("targetIndex for target1 should be cleaned") } - if _, exists := tm.targetIndex[target2]; exists { + if entry := tm.getTargetEntry(target2); entry != nil { t.Error("targetIndex for target2 should be cleaned") } } @@ -709,12 +697,12 @@ func TestMonitorsFor_RemoteTargets(t *testing.T) { } // Verify internal state: both relations stored - if len(tm.monitorRelations) != 2 { - t.Errorf("expected 2 monitorRelations, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 2 { + t.Errorf("expected 2 monitorRelations, got %d", tm.totalMonitors()) } // Verify targetIndex for remote target has consumer - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex for remoteTarget should exist") } @@ -745,18 +733,16 @@ func TestLinkAndMonitor_SameTarget_SeparateRelations(t *testing.T) { } // Verify stored separately - key := relationKey{consumer: consumer, target: target} - - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("Link should exist in linkRelations") } - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("Monitor should exist in monitorRelations") } // Verify targetIndex has consumer (shared) - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if _, exists := entry.consumers[consumer]; exists == false { t.Error("Consumer should be in targetIndex") } @@ -805,12 +791,12 @@ func TestEventsFor_Basic(t *testing.T) { } // Verify internal state: all events in events map - if len(tm.events) != 3 { - t.Errorf("expected 3 events in tm.events, got %d", len(tm.events)) + if tm.totalEvents() != 3 { + t.Errorf("expected 3 events in tm.events, got %d", tm.totalEvents()) } // Verify producerEvents has 3 events for this producer - producerEvts := tm.producerEvents[producer] + producerEvts := tm.getProducerEventsMap(producer) if producerEvts == nil { t.Fatal("producerEvents should exist for producer") } @@ -861,18 +847,18 @@ func TestEventsFor_AfterUnregister(t *testing.T) { // Verify internal state: event1 removed from events map event1 := gen.Event{Node: "node1", Name: "event1"} - if _, exists := tm.events[event1]; exists { + if entry := tm.getEventEntry(event1); entry != nil { t.Error("event1 should be removed from tm.events") } // Verify event2 still in events map event2 := gen.Event{Node: "node1", Name: "event2"} - if _, exists := tm.events[event2]; exists == false { + if entry := tm.getEventEntry(event2); entry == nil { t.Error("event2 should still exist in tm.events") } // Verify producerEvents has 1 event - producerEvts := tm.producerEvents[producer] + producerEvts := tm.getProducerEventsMap(producer) if len(producerEvts) != 1 { t.Errorf("expected 1 event in producerEvents, got %d", len(producerEvts)) } @@ -913,15 +899,15 @@ func TestEventsFor_AfterUnregisterAll(t *testing.T) { // Verify internal state: all events removed from events map event1 := gen.Event{Node: "node1", Name: "event1"} event2 := gen.Event{Node: "node1", Name: "event2"} - if _, exists := tm.events[event1]; exists { + if entry := tm.getEventEntry(event1); entry != nil { t.Error("event1 should be removed from tm.events") } - if _, exists := tm.events[event2]; exists { + if entry := tm.getEventEntry(event2); entry != nil { t.Error("event2 should be removed from tm.events") } // Verify producerEvents cleaned up - if _, exists := tm.producerEvents[producer]; exists { + if producerEvts := tm.getProducerEventsMap(producer); producerEvts != nil { t.Error("producerEvents for producer should be cleaned up") } } diff --git a/node/tm/scenarios_test.go b/node/tm/scenarios_test.go index fc4dc7522..3b7fd1afa 100644 --- a/node/tm/scenarios_test.go +++ b/node/tm/scenarios_test.go @@ -51,13 +51,12 @@ func TestScenario_TerminationReasons_Link(t *testing.T) { } // Verify internal state: linkRelations cleaned up - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("linkRelations should be cleaned after termination") } // Verify targetIndex cleaned up - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after termination") } }) @@ -96,13 +95,12 @@ func TestScenario_TerminationReasons_Monitor(t *testing.T) { } // Verify internal state: monitorRelations cleaned up - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("monitorRelations should be cleaned after termination") } // Verify targetIndex cleaned up - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after termination") } }) @@ -167,13 +165,13 @@ func TestScenario_ProcessTermination_CleansUpAllRelations(t *testing.T) { } // Verify targetIndex cleaned up for all targets - if _, exists := tm.targetIndex[target1]; exists { + if entry := tm.getTargetEntry(target1); entry != nil { t.Error("targetIndex for target1 should be cleaned") } - if _, exists := tm.targetIndex[target2]; exists { + if entry := tm.getTargetEntry(target2); entry != nil { t.Error("targetIndex for target2 should be cleaned") } - if _, exists := tm.targetIndex[target3]; exists { + if entry := tm.getTargetEntry(target3); entry != nil { t.Error("targetIndex for target3 should be cleaned") } } @@ -227,7 +225,7 @@ func TestScenario_MultipleConsumers_SameRemoteTarget_Link(t *testing.T) { } // Verify targetIndex has all 3 consumers - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -274,21 +272,18 @@ func TestScenario_MultipleConsumers_SameRemoteTarget_Monitor(t *testing.T) { } // Verify all relations stored - key1 := relationKey{consumer: consumer1, target: remoteTarget} - key2 := relationKey{consumer: consumer2, target: remoteTarget} - key3 := relationKey{consumer: consumer3, target: remoteTarget} - if _, exists := tm.monitorRelations[key1]; exists == false { + if exists := tm.hasMonitorRelation(consumer1, remoteTarget); exists == false { t.Error("consumer1 relation should exist in monitorRelations") } - if _, exists := tm.monitorRelations[key2]; exists == false { + if exists := tm.hasMonitorRelation(consumer2, remoteTarget); exists == false { t.Error("consumer2 relation should exist in monitorRelations") } - if _, exists := tm.monitorRelations[key3]; exists == false { + if exists := tm.hasMonitorRelation(consumer3, remoteTarget); exists == false { t.Error("consumer3 relation should exist in monitorRelations") } // Verify targetIndex has all 3 consumers - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex entry should exist") } @@ -332,7 +327,7 @@ func TestScenario_PartialUnlink_NoNetworkUnlinkUntilLast(t *testing.T) { t.Fatalf("expected 0 unlinks after P1, got %d", core.countSentUnlinks()) } // Verify targetIndex still has 2 consumers - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex should still exist after P1 unlink") } @@ -348,7 +343,7 @@ func TestScenario_PartialUnlink_NoNetworkUnlinkUntilLast(t *testing.T) { t.Fatalf("expected 0 unlinks after P2, got %d", core.countSentUnlinks()) } // Verify targetIndex still has 1 consumer - entry = tm.targetIndex[remoteTarget] + entry = tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex should still exist after P2 unlink") } @@ -364,7 +359,7 @@ func TestScenario_PartialUnlink_NoNetworkUnlinkUntilLast(t *testing.T) { t.Fatalf("expected 1 unlink after P3, got %d", core.countSentUnlinks()) } // Verify targetIndex cleaned up - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after last consumer unlinks") } } @@ -393,7 +388,7 @@ func TestScenario_PartialDemonitor_NoNetworkDemonitorUntilLast(t *testing.T) { t.Fatalf("expected 0 demonitors after P1,P2, got %d", core.countSentDemonitors()) } // Verify targetIndex still has 1 consumer (P3) - entry := tm.targetIndex[remoteTarget] + entry := tm.getTargetEntry(remoteTarget) if entry == nil { t.Fatal("targetIndex should still exist after P1,P2 demonitor") } @@ -407,7 +402,7 @@ func TestScenario_PartialDemonitor_NoNetworkDemonitorUntilLast(t *testing.T) { t.Fatalf("expected 1 demonitor after P3, got %d", core.countSentDemonitors()) } // Verify targetIndex cleaned up - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after last consumer demonitors") } } @@ -444,19 +439,16 @@ func TestScenario_RemoteTargetTermination_NotifiesAllLocalConsumers(t *testing.T } // Verify internal state cleaned up - key1 := relationKey{consumer: consumer1, target: remoteTarget} - key2 := relationKey{consumer: consumer2, target: remoteTarget} - key3 := relationKey{consumer: consumer3, target: remoteTarget} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, remoteTarget); exists { t.Error("consumer1 linkRelation should be cleaned") } - if _, exists := tm.linkRelations[key2]; exists { + if exists := tm.hasLinkRelation(consumer2, remoteTarget); exists { t.Error("consumer2 linkRelation should be cleaned") } - if _, exists := tm.linkRelations[key3]; exists { + if exists := tm.hasLinkRelation(consumer3, remoteTarget); exists { t.Error("consumer3 linkRelation should be cleaned") } - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -485,19 +477,16 @@ func TestScenario_RemoteTargetTermination_NotifiesAllLocalMonitors(t *testing.T) } // Verify internal state cleaned up - key1 := relationKey{consumer: consumer1, target: remoteTarget} - key2 := relationKey{consumer: consumer2, target: remoteTarget} - key3 := relationKey{consumer: consumer3, target: remoteTarget} - if _, exists := tm.monitorRelations[key1]; exists { + if exists := tm.hasMonitorRelation(consumer1, remoteTarget); exists { t.Error("consumer1 monitorRelation should be cleaned") } - if _, exists := tm.monitorRelations[key2]; exists { + if exists := tm.hasMonitorRelation(consumer2, remoteTarget); exists { t.Error("consumer2 monitorRelation should be cleaned") } - if _, exists := tm.monitorRelations[key3]; exists { + if exists := tm.hasMonitorRelation(consumer3, remoteTarget); exists { t.Error("consumer3 monitorRelation should be cleaned") } - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -532,11 +521,10 @@ func TestScenario_NodeDown_NotifiesAllLinkedConsumers(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: remoteTarget} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, remoteTarget); exists { t.Error("linkRelation should be cleaned after node down") } - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after node down") } } @@ -563,11 +551,10 @@ func TestScenario_NodeDown_NotifiesAllMonitoringConsumers(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: remoteTarget} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, remoteTarget); exists { t.Error("monitorRelation should be cleaned after node down") } - if _, exists := tm.targetIndex[remoteTarget]; exists { + if entry := tm.getTargetEntry(remoteTarget); entry != nil { t.Error("targetIndex should be cleaned after node down") } } @@ -601,18 +588,18 @@ func TestScenario_NodeDown_MultipleTargets(t *testing.T) { } // Verify all targetIndex entries cleaned up - if _, exists := tm.targetIndex[remoteTarget1]; exists { + if entry := tm.getTargetEntry(remoteTarget1); entry != nil { t.Error("targetIndex for remoteTarget1 should be cleaned") } - if _, exists := tm.targetIndex[remoteTarget2]; exists { + if entry := tm.getTargetEntry(remoteTarget2); entry != nil { t.Error("targetIndex for remoteTarget2 should be cleaned") } - if _, exists := tm.targetIndex[remoteTarget3]; exists { + if entry := tm.getTargetEntry(remoteTarget3); entry != nil { t.Error("targetIndex for remoteTarget3 should be cleaned") } // Verify all linkRelations cleaned up - if len(tm.linkRelations) != 0 { - t.Errorf("all linkRelations should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("all linkRelations should be cleaned, got %d", tm.totalLinks()) } } @@ -652,11 +639,10 @@ func TestScenario_LinkNode_ReceivesExitOnDisconnect(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: remoteNode} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, remoteNode); exists { t.Error("linkRelation should be cleaned after node disconnect") } - if _, exists := tm.targetIndex[remoteNode]; exists { + if entry := tm.getTargetEntry(remoteNode); entry != nil { t.Error("targetIndex should be cleaned after node disconnect") } } @@ -683,11 +669,10 @@ func TestScenario_MonitorNode_ReceivesDownOnDisconnect(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: remoteNode} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, remoteNode); exists { t.Error("monitorRelation should be cleaned after node disconnect") } - if _, exists := tm.targetIndex[remoteNode]; exists { + if entry := tm.getTargetEntry(remoteNode); entry != nil { t.Error("targetIndex should be cleaned after node disconnect") } } @@ -734,7 +719,7 @@ func TestScenario_RemoteCorePIDSubscribesEvent_FirstSubscriber_EventStart(t *tes } // Verify event entry has the subscriber - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry == nil { t.Fatal("event entry should exist") } @@ -778,7 +763,7 @@ func TestScenario_RemoteCorePIDUnsubscribesEvent_LastSubscriber_EventStop(t *tes } // Verify subscriber removed from event entry - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry == nil { t.Fatal("event entry should still exist (producer owns it)") } @@ -877,14 +862,13 @@ func TestScenario_MixedLinkMonitor_SameTarget(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("linkRelation should be cleaned after termination") } - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("monitorRelation should be cleaned after termination") } - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -916,11 +900,10 @@ func TestScenario_ProcessID_TerminationNotifiesMonitors(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: targetProcessID} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, targetProcessID); exists { t.Error("monitorRelation should be cleaned after termination") } - if _, exists := tm.targetIndex[targetProcessID]; exists { + if entry := tm.getTargetEntry(targetProcessID); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -947,11 +930,10 @@ func TestScenario_ProcessID_TerminationNotifiesLinkers(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: targetProcessID} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, targetProcessID); exists { t.Error("linkRelation should be cleaned after termination") } - if _, exists := tm.targetIndex[targetProcessID]; exists { + if entry := tm.getTargetEntry(targetProcessID); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -983,11 +965,10 @@ func TestScenario_Alias_TerminationNotifiesMonitors(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: targetAlias} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, targetAlias); exists { t.Error("monitorRelation should be cleaned after termination") } - if _, exists := tm.targetIndex[targetAlias]; exists { + if entry := tm.getTargetEntry(targetAlias); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -1014,11 +995,10 @@ func TestScenario_Alias_TerminationNotifiesLinkers(t *testing.T) { } // Verify internal state cleaned up - key := relationKey{consumer: consumer, target: targetAlias} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, targetAlias); exists { t.Error("linkRelation should be cleaned after termination") } - if _, exists := tm.targetIndex[targetAlias]; exists { + if entry := tm.getTargetEntry(targetAlias); entry != nil { t.Error("targetIndex should be cleaned after termination") } } @@ -1046,15 +1026,14 @@ func TestScenario_DuplicateLink_ReturnsError(t *testing.T) { } // Verify only 1 relation stored (not duplicated) - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists == false { + if exists := tm.hasLinkRelation(consumer, target); exists == false { t.Error("linkRelation should still exist") } - if len(tm.linkRelations) != 1 { - t.Errorf("expected exactly 1 linkRelation, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1 { + t.Errorf("expected exactly 1 linkRelation, got %d", tm.totalLinks()) } // Verify targetIndex has only 1 consumer - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should exist") } @@ -1081,15 +1060,14 @@ func TestScenario_DuplicateMonitor_ReturnsError(t *testing.T) { } // Verify only 1 relation stored (not duplicated) - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists == false { + if exists := tm.hasMonitorRelation(consumer, target); exists == false { t.Error("monitorRelation should still exist") } - if len(tm.monitorRelations) != 1 { - t.Errorf("expected exactly 1 monitorRelation, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 1 { + t.Errorf("expected exactly 1 monitorRelation, got %d", tm.totalMonitors()) } // Verify targetIndex has only 1 consumer - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetIndex should exist") } @@ -1752,11 +1730,11 @@ func TestMultipleConsumers_Link_AllNotified(t *testing.T) { } // Verify internal state cleaned up - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after termination") } - if len(tm.linkRelations) != 0 { - t.Errorf("all linkRelations should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("all linkRelations should be cleaned, got %d", tm.totalLinks()) } } @@ -1788,11 +1766,11 @@ func TestMultipleConsumers_Monitor_AllNotified(t *testing.T) { } // Verify internal state cleaned up - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after termination") } - if len(tm.monitorRelations) != 0 { - t.Errorf("all monitorRelations should be cleaned, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("all monitorRelations should be cleaned, got %d", tm.totalMonitors()) } } @@ -1887,7 +1865,7 @@ func TestRemoteLink_TwoConsumers_OneNetworkRequest(t *testing.T) { } // Verify targetIndex has 2 consumers - entry := tm.targetIndex[remotePID] + entry := tm.getTargetEntry(remotePID) if entry == nil { t.Fatal("targetIndex should exist") } @@ -1923,7 +1901,7 @@ func TestRemoteUnlink_LastConsumer_SendsNetworkUnlink(t *testing.T) { } // Verify targetIndex cleaned up - if _, exists := tm.targetIndex[remotePID]; exists { + if entry := tm.getTargetEntry(remotePID); entry != nil { t.Error("targetIndex should be cleaned after last consumer unlinks") } } @@ -2042,9 +2020,10 @@ func TestCorner_LinkFromTwoNodes(t *testing.T) { // Simulate node2's CorePID also linking coreNode2 := gen.PID{Node: "node2", ID: 1} + s := tm.shardFor(target) key := relationKey{consumer: coreNode2, target: target} - tm.linkRelations[key] = struct{}{} - entry := tm.targetIndex[target] + s.linkRelations[key] = struct{}{} + entry := s.targetIndex[target] if entry != nil { entry.consumers[coreNode2] = struct{}{} } @@ -2132,7 +2111,7 @@ func TestCorner_TargetIndexCleanedAfterRollback(t *testing.T) { tm.LinkPID(consumer, target) // Cleaned - if _, exists := tm.targetIndex[target]; exists { + if entry := tm.getTargetEntry(target); entry != nil { t.Error("targetIndex should be cleaned after rollback") } } @@ -2158,7 +2137,7 @@ func TestCorner_Event_ReSubscribe(t *testing.T) { t.Error("Re-subscribe should work") } - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 1 { t.Errorf("Counter should be 1, got %d", entry.subscriberCount) } @@ -2222,7 +2201,7 @@ func TestCorner_PublishEvent_NoSubscribers(t *testing.T) { } // Buffer updated - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.buffer.len != 1 { t.Error("Buffer should be updated") } @@ -2277,8 +2256,8 @@ func TestCorner_ConcurrentAdd(t *testing.T) { } // All stored - if len(tm.linkRelations) != 10 { - t.Errorf("Expected 10 links, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 10 { + t.Errorf("Expected 10 links, got %d", tm.totalLinks()) } // Only 1 network @@ -2343,8 +2322,8 @@ func TestStress_1000ConcurrentLinks(t *testing.T) { } // Verify all 1000 stored - if len(tm.linkRelations) != 1000 { - t.Errorf("Expected 1000 links, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1000 { + t.Errorf("Expected 1000 links, got %d", tm.totalLinks()) } // Only 1 network request (CorePID optimization!) @@ -2353,7 +2332,7 @@ func TestStress_1000ConcurrentLinks(t *testing.T) { } // Verify targetIndex has all 1000 - entry := tm.targetIndex[target] + entry := tm.getTargetEntry(target) if entry == nil { t.Fatal("targetEntry should exist") } @@ -2397,13 +2376,13 @@ func TestStress_ConcurrentAddRemove(t *testing.T) { time.Sleep(100 * time.Millisecond) // All should be cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be removed, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be removed, got %d", tm.totalLinks()) } // targetIndex should be clean (or have minimal entries) - if len(tm.targetIndex) > 0 { - t.Logf("targetIndex has %d entries (may be cleanup in progress)", len(tm.targetIndex)) + if tm.totalTargetIndex() > 0 { + t.Logf("targetIndex has %d entries (may be cleanup in progress)", tm.totalTargetIndex()) } } @@ -2428,7 +2407,7 @@ func TestStress_Event_1000Subscribers(t *testing.T) { } // Verify all subscribed - entry := tm.events[event] + entry := tm.getEventEntry(event) if len(entry.linkSubscribers) != 1000 { t.Errorf("Expected 1000 subscribers, got %d", len(entry.linkSubscribers)) } @@ -2489,12 +2468,12 @@ func TestStress_RapidSubscribeUnsubscribe(t *testing.T) { } // Should be clean - if len(tm.linkRelations) != 0 { - t.Errorf("linkRelations should be empty, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("linkRelations should be empty, got %d", tm.totalLinks()) } - if len(tm.targetIndex) != 0 { - t.Errorf("targetIndex should be empty, got %d", len(tm.targetIndex)) + if tm.totalTargetIndex() != 0 { + t.Errorf("targetIndex should be empty, got %d", tm.totalTargetIndex()) } } @@ -2514,8 +2493,8 @@ func TestStress_MassTermination(t *testing.T) { } // Verify 1000 links total - if len(tm.linkRelations) != 1000 { - t.Errorf("Expected 1000 links, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1000 { + t.Errorf("Expected 1000 links, got %d", tm.totalLinks()) } core.resetSentExits() @@ -2544,8 +2523,8 @@ func TestStress_MassTermination(t *testing.T) { } // All cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } // Check statistics @@ -2605,7 +2584,7 @@ func TestStress_Event_ConcurrentOperations(t *testing.T) { time.Sleep(200 * time.Millisecond) // Verify consistency - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry == nil { t.Fatal("Event should exist") } @@ -2654,8 +2633,8 @@ func TestStress_TerminatedNode_1000Subscriptions(t *testing.T) { } // All cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } } @@ -2675,23 +2654,23 @@ func TestStress_Memory_10KCycles(t *testing.T) { if i%1000 == 0 { // Check no memory leak every 1000 cycles - if len(tm.linkRelations) != 0 { - t.Errorf("Cycle %d: memory leak detected, %d relations", i, len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("Cycle %d: memory leak detected, %d relations", i, tm.totalLinks()) } - if len(tm.targetIndex) != 0 { - t.Errorf("Cycle %d: targetIndex leak, %d entries", i, len(tm.targetIndex)) + if tm.totalTargetIndex() != 0 { + t.Errorf("Cycle %d: targetIndex leak, %d entries", i, tm.totalTargetIndex()) } } } // Final check - if len(tm.linkRelations) != 0 { - t.Errorf("Final: linkRelations should be empty, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("Final: linkRelations should be empty, got %d", tm.totalLinks()) } - if len(tm.targetIndex) != 0 { - t.Errorf("Final: targetIndex should be empty, got %d", len(tm.targetIndex)) + if tm.totalTargetIndex() != 0 { + t.Errorf("Final: targetIndex should be empty, got %d", tm.totalTargetIndex()) } } @@ -2761,8 +2740,8 @@ func TestStress_ConcurrentTerminatedProcess(t *testing.T) { } // 1000 links total - if len(tm.linkRelations) != 1000 { - t.Errorf("Expected 1000 links, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1000 { + t.Errorf("Expected 1000 links, got %d", tm.totalLinks()) } var wg sync.WaitGroup @@ -2784,8 +2763,8 @@ func TestStress_ConcurrentTerminatedProcess(t *testing.T) { time.Sleep(500 * time.Millisecond) // All cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } // Remote Unlinks sent (500 consumers × 2 targets but CorePID optimization) @@ -2834,12 +2813,12 @@ func TestStress_MixedOperations(t *testing.T) { time.Sleep(200 * time.Millisecond) // Should be mostly clean - if len(tm.linkRelations) != 0 { - t.Logf("linkRelations: %d (some may be in flight)", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Logf("linkRelations: %d (some may be in flight)", tm.totalLinks()) } - if len(tm.monitorRelations) != 0 { - t.Logf("monitorRelations: %d (some may be in flight)", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Logf("monitorRelations: %d (some may be in flight)", tm.totalMonitors()) } } @@ -2863,8 +2842,8 @@ func TestStress_WorkerSpawnCycles(t *testing.T) { } // All 1000 links stored - if len(tm.linkRelations) != 1000 { - t.Errorf("Expected 1000 links, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1000 { + t.Errorf("Expected 1000 links, got %d", tm.totalLinks()) } // Worker should have spawned and slept multiple times diff --git a/node/tm/terminate.go b/node/tm/terminate.go index 78bb1074f..0b9b422c8 100644 --- a/node/tm/terminate.go +++ b/node/tm/terminate.go @@ -3,21 +3,20 @@ package tm import "ergo.services/ergo/gen" func (tm *targetManager) TerminatedTargetPID(pid gen.PID, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(pid) + s.mutex.Lock() remoteNodesLinks := make(map[gen.Atom]bool) remoteNodesMonitors := make(map[gen.Atom]bool) var localExitConsumers []gen.PID var localDownConsumers []gen.PID - // Process link consumers - for key := range tm.linkRelations { + for key := range s.linkRelations { if key.target != pid { continue } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodesLinks[key.consumer.Node] = true @@ -27,13 +26,12 @@ func (tm *targetManager) TerminatedTargetPID(pid gen.PID, reason error) { localExitConsumers = append(localExitConsumers, key.consumer) } - // Process monitor consumers - for key := range tm.monitorRelations { + for key := range s.monitorRelations { if key.target != pid { continue } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodesMonitors[key.consumer.Node] = true @@ -43,14 +41,15 @@ func (tm *targetManager) TerminatedTargetPID(pid gen.PID, reason error) { localDownConsumers = append(localDownConsumers, key.consumer) } - // Send exit messages to local consumers + delete(s.targetIndex, pid) + s.mutex.Unlock() + if len(localExitConsumers) > 0 { tm.exitSignalsProduced.Add(1) tm.core.RouteSendExitMessages(pid, localExitConsumers, gen.MessageExitPID{PID: pid, Reason: reason}) tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) } - // Send down messages to local consumers if len(localDownConsumers) > 0 { tm.downMessagesProduced.Add(1) for _, consumer := range localDownConsumers { @@ -59,7 +58,6 @@ func (tm *targetManager) TerminatedTargetPID(pid gen.PID, reason error) { tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) } - // Send to remote nodes for node := range remoteNodesLinks { connection, err := tm.core.GetConnection(node) if err != nil { @@ -75,25 +73,22 @@ func (tm *targetManager) TerminatedTargetPID(pid gen.PID, reason error) { } connection.SendTerminatePID(pid, reason) } - - delete(tm.targetIndex, pid) } func (tm *targetManager) TerminatedTargetProcessID(processID gen.ProcessID, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(processID) + s.mutex.Lock() remoteNodes := make(map[gen.Atom]bool) var localExitConsumers []gen.PID var localDownConsumers []gen.PID - // Link consumers - for key := range tm.linkRelations { + for key := range s.linkRelations { if key.target != processID { continue } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -103,13 +98,12 @@ func (tm *targetManager) TerminatedTargetProcessID(processID gen.ProcessID, reas localExitConsumers = append(localExitConsumers, key.consumer) } - // Monitor consumers - for key := range tm.monitorRelations { + for key := range s.monitorRelations { if key.target != processID { continue } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -119,14 +113,15 @@ func (tm *targetManager) TerminatedTargetProcessID(processID gen.ProcessID, reas localDownConsumers = append(localDownConsumers, key.consumer) } - // Send exit messages + delete(s.targetIndex, processID) + s.mutex.Unlock() + if len(localExitConsumers) > 0 { tm.exitSignalsProduced.Add(1) tm.core.RouteSendExitMessages(tm.core.PID(), localExitConsumers, gen.MessageExitProcessID{ProcessID: processID, Reason: reason}) tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) } - // Send down messages if len(localDownConsumers) > 0 { tm.downMessagesProduced.Add(1) for _, consumer := range localDownConsumers { @@ -135,7 +130,6 @@ func (tm *targetManager) TerminatedTargetProcessID(processID gen.ProcessID, reas tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) } - // Send to remote nodes for node := range remoteNodes { connection, err := tm.core.GetConnection(node) if err != nil { @@ -143,25 +137,22 @@ func (tm *targetManager) TerminatedTargetProcessID(processID gen.ProcessID, reas } connection.SendTerminateProcessID(processID, reason) } - - delete(tm.targetIndex, processID) } func (tm *targetManager) TerminatedTargetAlias(alias gen.Alias, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(alias) + s.mutex.Lock() remoteNodes := make(map[gen.Atom]bool) var localExitConsumers []gen.PID var localDownConsumers []gen.PID - // Link consumers - for key := range tm.linkRelations { + for key := range s.linkRelations { if key.target != alias { continue } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -171,13 +162,12 @@ func (tm *targetManager) TerminatedTargetAlias(alias gen.Alias, reason error) { localExitConsumers = append(localExitConsumers, key.consumer) } - // Monitor consumers - for key := range tm.monitorRelations { + for key := range s.monitorRelations { if key.target != alias { continue } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -187,14 +177,15 @@ func (tm *targetManager) TerminatedTargetAlias(alias gen.Alias, reason error) { localDownConsumers = append(localDownConsumers, key.consumer) } - // Send exit messages + delete(s.targetIndex, alias) + s.mutex.Unlock() + if len(localExitConsumers) > 0 { tm.exitSignalsProduced.Add(1) tm.core.RouteSendExitMessages(tm.core.PID(), localExitConsumers, gen.MessageExitAlias{Alias: alias, Reason: reason}) tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) } - // Send down messages if len(localDownConsumers) > 0 { tm.downMessagesProduced.Add(1) for _, consumer := range localDownConsumers { @@ -203,7 +194,6 @@ func (tm *targetManager) TerminatedTargetAlias(alias gen.Alias, reason error) { tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) } - // Send to remote nodes for node := range remoteNodes { connection, err := tm.core.GetConnection(node) if err != nil { @@ -211,25 +201,22 @@ func (tm *targetManager) TerminatedTargetAlias(alias gen.Alias, reason error) { } connection.SendTerminateAlias(alias, reason) } - - delete(tm.targetIndex, alias) } func (tm *targetManager) TerminatedTargetEvent(event gen.Event, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + s := tm.shardFor(event) + s.mutex.Lock() remoteNodes := make(map[gen.Atom]bool) var localExitConsumers []gen.PID var localDownConsumers []gen.PID - // Link consumers - for key := range tm.linkRelations { + for key := range s.linkRelations { if key.target != event { continue } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -239,13 +226,12 @@ func (tm *targetManager) TerminatedTargetEvent(event gen.Event, reason error) { localExitConsumers = append(localExitConsumers, key.consumer) } - // Monitor consumers - for key := range tm.monitorRelations { + for key := range s.monitorRelations { if key.target != event { continue } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) if key.consumer.Node != tm.core.Name() { remoteNodes[key.consumer.Node] = true @@ -255,14 +241,16 @@ func (tm *targetManager) TerminatedTargetEvent(event gen.Event, reason error) { localDownConsumers = append(localDownConsumers, key.consumer) } - // Send exit messages + delete(s.events, event) + delete(s.targetIndex, event) + s.mutex.Unlock() + if len(localExitConsumers) > 0 { tm.exitSignalsProduced.Add(1) tm.core.RouteSendExitMessages(tm.core.PID(), localExitConsumers, gen.MessageExitEvent{Event: event, Reason: reason}) tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) } - // Send down messages if len(localDownConsumers) > 0 { tm.downMessagesProduced.Add(1) for _, consumer := range localDownConsumers { @@ -271,7 +259,6 @@ func (tm *targetManager) TerminatedTargetEvent(event gen.Event, reason error) { tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) } - // Send to remote nodes for node := range remoteNodes { connection, err := tm.core.GetConnection(node) if err != nil { @@ -279,73 +266,71 @@ func (tm *targetManager) TerminatedTargetEvent(event gen.Event, reason error) { } connection.SendTerminateEvent(event, reason) } - - // Cleanup event from events map - delete(tm.events, event) - delete(tm.targetIndex, event) } func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + for i := range tm.shards { + tm.terminateNodeInShard(&tm.shards[i], node, reason) + } +} + +func (tm *targetManager) terminateNodeInShard(s *shard, node gen.Atom, reason error) { + s.mutex.Lock() - // Collect exit messages by type - exitPID := make(map[gen.PID][]gen.PID) // target -> consumers + exitPID := make(map[gen.PID][]gen.PID) exitProcessID := make(map[gen.ProcessID][]gen.PID) exitAlias := make(map[gen.Alias][]gen.PID) exitEvent := make(map[gen.Event][]gen.PID) exitNode := make(map[gen.Atom][]gen.PID) - // Cleanup linkRelations - for key := range tm.linkRelations { + for key := range s.linkRelations { shouldRemove := false - // Consumer on terminated node if key.consumer.Node == node { shouldRemove = true } - // Target on terminated node if shouldRemove == false { switch t := key.target.(type) { case gen.PID: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - exitPID[t] = append(exitPID[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + exitPID[t] = append(exitPID[t], key.consumer) } - case gen.ProcessID: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - exitProcessID[t] = append(exitProcessID[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + exitProcessID[t] = append(exitProcessID[t], key.consumer) } - case gen.Alias: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - exitAlias[t] = append(exitAlias[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + exitAlias[t] = append(exitAlias[t], key.consumer) } - case gen.Event: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - exitEvent[t] = append(exitEvent[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + exitEvent[t] = append(exitEvent[t], key.consumer) } - case gen.Atom: - if t == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - exitNode[t] = append(exitNode[t], key.consumer) - } + if t != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + exitNode[t] = append(exitNode[t], key.consumer) } } } @@ -354,29 +339,26 @@ func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { continue } - delete(tm.linkRelations, key) + delete(s.linkRelations, key) - entry := tm.targetIndex[key.target] + entry := s.targetIndex[key.target] if entry == nil { continue } delete(entry.consumers, key.consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, key.target) + delete(s.targetIndex, key.target) } } - // Collect down messages by type downPID := make(map[gen.PID][]gen.PID) downProcessID := make(map[gen.ProcessID][]gen.PID) downAlias := make(map[gen.Alias][]gen.PID) downEvent := make(map[gen.Event][]gen.PID) downNode := make(map[gen.Atom][]gen.PID) - // Cleanup monitorRelations - for key := range tm.monitorRelations { + for key := range s.monitorRelations { shouldRemove := false if key.consumer.Node == node { @@ -386,43 +368,44 @@ func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { if shouldRemove == false { switch t := key.target.(type) { case gen.PID: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - downPID[t] = append(downPID[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + downPID[t] = append(downPID[t], key.consumer) } - case gen.ProcessID: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - downProcessID[t] = append(downProcessID[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + downProcessID[t] = append(downProcessID[t], key.consumer) } - case gen.Alias: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - downAlias[t] = append(downAlias[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + downAlias[t] = append(downAlias[t], key.consumer) } - case gen.Event: - if t.Node == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - downEvent[t] = append(downEvent[t], key.consumer) - } + if t.Node != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + downEvent[t] = append(downEvent[t], key.consumer) } - case gen.Atom: - if t == node { - shouldRemove = true - if key.consumer.Node == tm.core.Name() { - downNode[t] = append(downNode[t], key.consumer) - } + if t != node { + break + } + shouldRemove = true + if key.consumer.Node == tm.core.Name() { + downNode[t] = append(downNode[t], key.consumer) } } } @@ -431,21 +414,29 @@ func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { continue } - delete(tm.monitorRelations, key) + delete(s.monitorRelations, key) - entry := tm.targetIndex[key.target] + entry := s.targetIndex[key.target] if entry == nil { continue } delete(entry.consumers, key.consumer) - if len(entry.consumers) == 0 { - delete(tm.targetIndex, key.target) + delete(s.targetIndex, key.target) } } - // Send exit messages (batch per target) + // Cleanup events from terminated node + for event := range s.events { + if event.Node == node { + delete(s.events, event) + } + } + + s.mutex.Unlock() + + // Dispatch exit messages for target, consumers := range exitPID { tm.exitSignalsProduced.Add(1) tm.core.RouteSendExitMessages(tm.core.PID(), consumers, gen.MessageExitPID{PID: target, Reason: gen.ErrNoConnection}) @@ -472,7 +463,7 @@ func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { tm.exitSignalsDelivered.Add(int64(len(consumers))) } - // Send down messages + // Dispatch down messages for target, consumers := range downPID { tm.downMessagesProduced.Add(1) for _, consumer := range consumers { @@ -508,317 +499,242 @@ func (tm *targetManager) TerminatedTargetNode(node gen.Atom, reason error) { } tm.downMessagesDelivered.Add(int64(len(consumers))) } - - // Cleanup events from terminated node - for event := range tm.events { - if event.Node == node { - delete(tm.events, event) - } - } } func (tm *targetManager) TerminatedProcess(pid gen.PID, reason error) { - tm.mutex.Lock() - defer tm.mutex.Unlock() + for i := range tm.shards { + tm.terminateProcessInShard(&tm.shards[i], pid, reason) + } +} - // CleanupConsumer - cleanup all subscriptions this process had +func (tm *targetManager) terminateProcessInShard(s *shard, pid gen.PID, reason error) { + s.mutex.Lock() - // Process linkRelations - for key := range tm.linkRelations { + for key := range s.linkRelations { if key.consumer != pid { continue } - delete(tm.linkRelations, key) - - // Handle events separately (need to decrement counter) - if event, ok := key.target.(gen.Event); ok { - if event.Node == tm.core.Name() { - entry := tm.events[event] - if entry != nil { - // Swap-delete from linkSubscribers - if idx, exists := entry.linkSubscribersIndex[pid]; exists { - last := len(entry.linkSubscribers) - 1 - if idx != last { - entry.linkSubscribers[idx] = entry.linkSubscribers[last] - entry.linkSubscribersIndex[entry.linkSubscribers[idx]] = idx - } - entry.linkSubscribers = entry.linkSubscribers[:last] - delete(entry.linkSubscribersIndex, pid) - } - entry.subscriberCount-- + delete(s.linkRelations, key) - if entry.subscriberCount == 0 && entry.notify { - tm.core.RouteSendPID(tm.core.PID(), entry.producer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageEventStop{Name: event.Name}) + event, ok := key.target.(gen.Event) + if ok == true && event.Node == tm.core.Name() { + entry := s.events[event] + if entry != nil { + idx, exists := entry.linkSubscribersIndex[pid] + if exists == true { + last := len(entry.linkSubscribers) - 1 + if idx != last { + entry.linkSubscribers[idx] = entry.linkSubscribers[last] + entry.linkSubscribersIndex[entry.linkSubscribers[idx]] = idx } + entry.linkSubscribers = entry.linkSubscribers[:last] + delete(entry.linkSubscribersIndex, pid) + } + entry.subscriberCount-- + if entry.subscriberCount == 0 && entry.notify { + tm.core.RouteSendPID(tm.core.PID(), entry.producer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageEventStop{Name: event.Name}) } } } - entry := tm.targetIndex[key.target] - if entry == nil { + tm.cleanupTargetEntry(s, pid, key.target, true) + } + + for key := range s.monitorRelations { + if key.consumer != pid { continue } - delete(entry.consumers, key.consumer) - - isLast := (len(entry.consumers) == 0) + delete(s.monitorRelations, key) - if isLast { - delete(tm.targetIndex, key.target) + event, ok := key.target.(gen.Event) + if ok == true && event.Node == tm.core.Name() { + entry := s.events[event] + if entry != nil { + idx, exists := entry.monitorSubscribersIndex[pid] + if exists == true { + last := len(entry.monitorSubscribers) - 1 + if idx != last { + entry.monitorSubscribers[idx] = entry.monitorSubscribers[last] + entry.monitorSubscribersIndex[entry.monitorSubscribers[idx]] = idx + } + entry.monitorSubscribers = entry.monitorSubscribers[:last] + delete(entry.monitorSubscribersIndex, pid) + } + entry.subscriberCount-- + if entry.subscriberCount == 0 && entry.notify { + tm.core.RouteSendPID(tm.core.PID(), entry.producer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageEventStop{Name: event.Name}) + } + } } - // Check if target is remote and need to send Unlink - isRemote := false - var targetNode gen.Atom + tm.cleanupTargetEntry(s, pid, key.target, false) + } - switch t := key.target.(type) { - case gen.PID: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) + // Producer cleanup + tm.cleanupProducerInShard(s, pid, reason) - case gen.ProcessID: - if t.Node == "" { - targetNode = tm.core.Name() - } else { - targetNode = t.Node - } - isRemote = (targetNode != tm.core.Name()) + s.mutex.Unlock() +} - case gen.Alias: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) +// cleanupTargetEntry handles targetIndex update and remote unlink/demonitor. +func (tm *targetManager) cleanupTargetEntry(s *shard, consumer gen.PID, target any, isLink bool) { + entry := s.targetIndex[target] + if entry == nil { + return + } - case gen.Event: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) + delete(entry.consumers, consumer) + isLast := (len(entry.consumers) == 0) + if isLast { + delete(s.targetIndex, target) + } - case gen.Atom: - isRemote = false - } + isRemote := false + var targetNode gen.Atom - if isRemote == false { - continue + switch t := target.(type) { + case gen.PID: + targetNode = t.Node + isRemote = (t.Node != tm.core.Name()) + case gen.ProcessID: + if t.Node == "" { + targetNode = tm.core.Name() + } else { + targetNode = t.Node } + isRemote = (targetNode != tm.core.Name()) + case gen.Alias: + targetNode = t.Node + isRemote = (t.Node != tm.core.Name()) + case gen.Event: + targetNode = t.Node + isRemote = (t.Node != tm.core.Name()) + case gen.Atom: + isRemote = false + } - // Remote target - check if last local consumer - if isLast == false { - hasLocal := false - for p := range entry.consumers { - if p.Node == tm.core.Name() && p != tm.core.PID() { - hasLocal = true - break - } - } + if isRemote == false { + return + } - if hasLocal { - continue + if isLast == false { + hasLocal := false + for p := range entry.consumers { + if p.Node == tm.core.Name() && p != tm.core.PID() { + hasLocal = true + break } } - - // Last local consumer - send remote Unlink - connection, err := tm.core.GetConnection(targetNode) - if err != nil { - continue + if hasLocal { + return } + } - switch t := key.target.(type) { + connection, err := tm.core.GetConnection(targetNode) + if err != nil { + return + } + + if isLink { + switch t := target.(type) { case gen.PID: connection.UnlinkPID(tm.core.PID(), t) - case gen.ProcessID: connection.UnlinkProcessID(tm.core.PID(), t) - case gen.Alias: connection.UnlinkAlias(tm.core.PID(), t) - case gen.Event: connection.UnlinkEvent(tm.core.PID(), t) } - } - - // Process monitorRelations - for key := range tm.monitorRelations { - if key.consumer != pid { - continue - } - - delete(tm.monitorRelations, key) - - // Handle events - if event, ok := key.target.(gen.Event); ok { - if event.Node == tm.core.Name() { - entry := tm.events[event] - if entry != nil { - // Swap-delete from monitorSubscribers - if idx, exists := entry.monitorSubscribersIndex[pid]; exists { - last := len(entry.monitorSubscribers) - 1 - if idx != last { - entry.monitorSubscribers[idx] = entry.monitorSubscribers[last] - entry.monitorSubscribersIndex[entry.monitorSubscribers[idx]] = idx - } - entry.monitorSubscribers = entry.monitorSubscribers[:last] - delete(entry.monitorSubscribersIndex, pid) - } - entry.subscriberCount-- - - if entry.subscriberCount == 0 && entry.notify { - tm.core.RouteSendPID(tm.core.PID(), entry.producer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageEventStop{Name: event.Name}) - } - } - } - } - - entry := tm.targetIndex[key.target] - if entry == nil { - continue - } - - delete(entry.consumers, key.consumer) - - isLast := (len(entry.consumers) == 0) - - if isLast { - delete(tm.targetIndex, key.target) - } - - // Check remote and send Demonitor - isRemote := false - var targetNode gen.Atom - - switch t := key.target.(type) { - case gen.PID: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) - - case gen.ProcessID: - if t.Node == "" { - targetNode = tm.core.Name() - } else { - targetNode = t.Node - } - isRemote = (targetNode != tm.core.Name()) - - case gen.Alias: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) - - case gen.Event: - targetNode = t.Node - isRemote = (t.Node != tm.core.Name()) - - case gen.Atom: - isRemote = false - } - - if isRemote == false { - continue - } - - if isLast == false { - hasLocal := false - for p := range entry.consumers { - if p.Node == tm.core.Name() && p != tm.core.PID() { - hasLocal = true - break - } - } - - if hasLocal { - continue - } - } - - // Last local consumer - send remote Demonitor - connection, err := tm.core.GetConnection(targetNode) - if err != nil { - continue - } - - switch t := key.target.(type) { + } else { + switch t := target.(type) { case gen.PID: connection.DemonitorPID(tm.core.PID(), t) - case gen.ProcessID: connection.DemonitorProcessID(tm.core.PID(), t) - case gen.Alias: connection.DemonitorAlias(tm.core.PID(), t) - case gen.Event: connection.DemonitorEvent(tm.core.PID(), t) } } +} - // Cleanup events owned by terminated process (PRODUCER cleanup) - if events := tm.producerEvents[pid]; events != nil { - remoteEvents := make(map[gen.Atom][]gen.Event) +// cleanupProducerInShard handles events owned by terminated process within a shard. +func (tm *targetManager) cleanupProducerInShard(s *shard, pid gen.PID, reason error) { + events := s.producerEvents[pid] + if events == nil { + return + } - for event := range events { - entry := tm.events[event] - if entry == nil { - continue - } + remoteEvents := make(map[gen.Atom][]gen.Event) - // Send exit to link subscribers - var localExitConsumers []gen.PID - for _, consumer := range entry.linkSubscribers { - if consumer.Node != tm.core.Name() { - remoteEvents[consumer.Node] = append(remoteEvents[consumer.Node], event) - continue - } - localExitConsumers = append(localExitConsumers, consumer) - } - if len(localExitConsumers) > 0 { - tm.exitSignalsProduced.Add(1) - tm.core.RouteSendExitMessages(tm.core.PID(), localExitConsumers, gen.MessageExitEvent{Event: event, Reason: reason}) - tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) - } + for event := range events { + entry := s.events[event] + if entry == nil { + continue + } - // Send down to monitor subscribers - var localDownConsumers []gen.PID - for _, consumer := range entry.monitorSubscribers { - if consumer.Node != tm.core.Name() { - remoteEvents[consumer.Node] = append(remoteEvents[consumer.Node], event) - continue - } - localDownConsumers = append(localDownConsumers, consumer) - } - if len(localDownConsumers) > 0 { - tm.downMessagesProduced.Add(1) - for _, consumer := range localDownConsumers { - tm.core.RouteSendPID(tm.core.PID(), consumer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageDownEvent{Event: event, Reason: reason}) - } - tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) + // Send exit to link subscribers + var localExitConsumers []gen.PID + for _, consumer := range entry.linkSubscribers { + if consumer.Node != tm.core.Name() { + remoteEvents[consumer.Node] = append(remoteEvents[consumer.Node], event) + continue } + localExitConsumers = append(localExitConsumers, consumer) + } + if len(localExitConsumers) > 0 { + tm.exitSignalsProduced.Add(1) + tm.core.RouteSendExitMessages(tm.core.PID(), localExitConsumers, gen.MessageExitEvent{Event: event, Reason: reason}) + tm.exitSignalsDelivered.Add(int64(len(localExitConsumers))) + } - // Cleanup relations for this event - for key := range tm.linkRelations { - if key.target == event { - delete(tm.linkRelations, key) - } + // Send down to monitor subscribers + var localDownConsumers []gen.PID + for _, consumer := range entry.monitorSubscribers { + if consumer.Node != tm.core.Name() { + remoteEvents[consumer.Node] = append(remoteEvents[consumer.Node], event) + continue } - for key := range tm.monitorRelations { - if key.target == event { - delete(tm.monitorRelations, key) - } + localDownConsumers = append(localDownConsumers, consumer) + } + if len(localDownConsumers) > 0 { + tm.downMessagesProduced.Add(1) + for _, consumer := range localDownConsumers { + tm.core.RouteSendPID(tm.core.PID(), consumer, gen.MessageOptions{Priority: gen.MessagePriorityHigh}, gen.MessageDownEvent{Event: event, Reason: reason}) } - - delete(tm.targetIndex, event) - delete(tm.events, event) + tm.downMessagesDelivered.Add(int64(len(localDownConsumers))) } - // Send to remote nodes - for remoteNode, nodeEvents := range remoteEvents { - connection, err := tm.core.GetConnection(remoteNode) - if err != nil { - continue + // Cleanup relations for this event + for key := range s.linkRelations { + if key.target == event { + delete(s.linkRelations, key) } - for _, event := range nodeEvents { - connection.SendTerminateEvent(event, reason) + } + for key := range s.monitorRelations { + if key.target == event { + delete(s.monitorRelations, key) } } - delete(tm.producerEvents, pid) + delete(s.targetIndex, event) + delete(s.events, event) + } + + // Send to remote nodes + for remoteNode, nodeEvents := range remoteEvents { + connection, err := tm.core.GetConnection(remoteNode) + if err != nil { + continue + } + for _, event := range nodeEvents { + connection.SendTerminateEvent(event, reason) + } } + + delete(s.producerEvents, pid) } diff --git a/node/tm/terminate_test.go b/node/tm/terminate_test.go index d329e83b2..11028e286 100644 --- a/node/tm/terminate_test.go +++ b/node/tm/terminate_test.go @@ -34,13 +34,12 @@ func TestTerminatedTargetPID_LinkSubscribers(t *testing.T) { } // Verify subscriptions cleaned - key1 := relationKey{consumer: consumer1, target: target} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, target); exists { t.Error("Link should be removed after target terminated") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -72,8 +71,8 @@ func TestTerminatedTargetPID_MonitorSubscribers(t *testing.T) { } // Verify cleaned - if len(tm.monitorRelations) != 0 { - t.Errorf("monitorRelations should be empty, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("monitorRelations should be empty, got %d", tm.totalMonitors()) } } @@ -108,17 +107,17 @@ func TestTerminatedTargetPID_Mixed(t *testing.T) { } // Verify linkRelations cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("linkRelations should be empty, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("linkRelations should be empty, got %d", tm.totalLinks()) } // Verify monitorRelations cleaned - if len(tm.monitorRelations) != 0 { - t.Errorf("monitorRelations should be empty, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("monitorRelations should be empty, got %d", tm.totalMonitors()) } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -145,13 +144,12 @@ func TestTerminatedTargetProcessID(t *testing.T) { } // Cleaned from linkRelations - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -177,13 +175,12 @@ func TestTerminatedTargetAlias(t *testing.T) { } // Verify linkRelations cleaned - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(consumer, target); exists { t.Error("Link should be removed") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -198,11 +195,12 @@ func TestTerminatedTargetNode_RemoteConsumer(t *testing.T) { // Remote consumer links to local target // (Simulates: node2's CorePID linked to node1's process) - tm.linkRelations[relationKey{consumer: remoteConsumer, target: localTarget}] = struct{}{} + s := tm.shardFor(localTarget) + s.linkRelations[relationKey{consumer: remoteConsumer, target: localTarget}] = struct{}{} entry := &targetEntry{consumers: make(map[gen.PID]struct{})} entry.consumers[remoteConsumer] = struct{}{} - tm.targetIndex[localTarget] = entry + s.targetIndex[localTarget] = entry core.resetSentExits() @@ -217,8 +215,7 @@ func TestTerminatedTargetNode_RemoteConsumer(t *testing.T) { } // But subscription cleaned! - key := relationKey{consumer: remoteConsumer, target: localTarget} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(remoteConsumer, localTarget); exists { t.Error("Link from remote consumer should be removed") } } @@ -247,13 +244,12 @@ func TestTerminatedTargetNode_RemoteTarget(t *testing.T) { } // Cleaned from linkRelations - key := relationKey{consumer: localConsumer, target: remoteTarget} - if _, exists := tm.linkRelations[key]; exists { + if exists := tm.hasLinkRelation(localConsumer, remoteTarget); exists { t.Error("Link should be removed") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[remoteTarget]; exists { + if tm.getTargetEntry(remoteTarget) != nil { t.Error("targetIndex should be cleaned") } } @@ -273,7 +269,8 @@ func TestTerminatedTargetNode_Mixed(t *testing.T) { tm.LinkPID(localConsumer, remoteTarget) // Remote → Local (manual setup) - tm.linkRelations[relationKey{consumer: remoteConsumer, target: localTarget}] = struct{}{} + s := tm.shardFor(localTarget) + s.linkRelations[relationKey{consumer: remoteConsumer, target: localTarget}] = struct{}{} core.resetSentExits() @@ -288,12 +285,12 @@ func TestTerminatedTargetNode_Mixed(t *testing.T) { } // Both links cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } // Verify targetIndex cleaned for remoteTarget - if _, exists := tm.targetIndex[remoteTarget]; exists { + if tm.getTargetEntry(remoteTarget) != nil { t.Error("targetIndex for remoteTarget should be cleaned") } } @@ -305,7 +302,8 @@ func TestTerminatedTargetNode_EventsCleaned(t *testing.T) { // Manually add event from node2 event := gen.Event{Node: "node2", Name: "test"} - tm.events[event] = &eventEntry{ + s := tm.shardFor(event) + s.events[event] = &eventEntry{ producer: gen.PID{Node: "node2", ID: 100}, } @@ -315,7 +313,7 @@ func TestTerminatedTargetNode_EventsCleaned(t *testing.T) { time.Sleep(50 * time.Millisecond) // Event cleaned - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event from terminated node should be removed") } } @@ -342,13 +340,12 @@ func TestTerminatedTargetProcessID_Monitors(t *testing.T) { } // Verify monitorRelations cleaned - key := relationKey{consumer: consumer, target: target} - if _, exists := tm.monitorRelations[key]; exists { + if exists := tm.hasMonitorRelation(consumer, target); exists { t.Error("Monitor should be removed") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -374,7 +371,7 @@ func TestTerminatedTargetAlias_Monitors(t *testing.T) { } // Cleaned - if len(tm.monitorRelations) != 0 { + if tm.totalMonitors() != 0 { t.Error("monitorRelations should be empty") } } @@ -438,18 +435,18 @@ func TestTerminatedTargetNode_MultipleTypes(t *testing.T) { } // All links cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } // Verify all targetIndex entries cleaned - if _, exists := tm.targetIndex[pidTarget]; exists { + if tm.getTargetEntry(pidTarget) != nil { t.Error("targetIndex for pidTarget should be cleaned") } - if _, exists := tm.targetIndex[processIDTarget]; exists { + if tm.getTargetEntry(processIDTarget) != nil { t.Error("targetIndex for processIDTarget should be cleaned") } - if _, exists := tm.targetIndex[aliasTarget]; exists { + if tm.getTargetEntry(aliasTarget) != nil { t.Error("targetIndex for aliasTarget should be cleaned") } } @@ -493,8 +490,8 @@ func TestTerminatedProcess_CleanupLinks(t *testing.T) { time.Sleep(50 * time.Millisecond) // Links cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("All links should be cleaned, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("All links should be cleaned, got %d", tm.totalLinks()) } // Remote Unlink sent @@ -503,10 +500,10 @@ func TestTerminatedProcess_CleanupLinks(t *testing.T) { } // Verify targetIndex cleaned for both targets - if _, exists := tm.targetIndex[target1]; exists { + if tm.getTargetEntry(target1) != nil { t.Error("targetIndex for target1 should be cleaned") } - if _, exists := tm.targetIndex[target2]; exists { + if tm.getTargetEntry(target2) != nil { t.Error("targetIndex for target2 should be cleaned") } } @@ -540,7 +537,7 @@ func TestTerminatedProcess_LastSubscriber_EventStop(t *testing.T) { } // Counter = 0 - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 0 { t.Errorf("subscriberCount should be 0, got %d", entry.subscriberCount) } @@ -576,20 +573,18 @@ func TestTerminatedProcess_NotLast_NoEventStop(t *testing.T) { } // Counter = 1 - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 1 { t.Errorf("subscriberCount should be 1, got %d", entry.subscriberCount) } // Verify consumer1 removed from linkRelations - key1 := relationKey{consumer: consumer1, target: event} - if _, exists := tm.linkRelations[key1]; exists { + if exists := tm.hasLinkRelation(consumer1, event); exists { t.Error("consumer1 link should be removed") } // Verify consumer2 still in linkRelations - key2 := relationKey{consumer: consumer2, target: event} - if _, exists := tm.linkRelations[key2]; exists == false { + if exists := tm.hasLinkRelation(consumer2, event); exists == false { t.Error("consumer2 link should still exist") } } @@ -613,12 +608,12 @@ func TestTerminatedProcess_RemoteEvent_LastLocal_SendsUnlink(t *testing.T) { time.Sleep(50 * time.Millisecond) // Verify linkRelations cleaned - if len(tm.linkRelations) != 0 { + if tm.totalLinks() != 0 { t.Error("Link should be cleaned") } // Verify targetIndex cleaned (last local subscriber) - if _, exists := tm.targetIndex[event]; exists { + if tm.getTargetEntry(event) != nil { t.Error("targetIndex should be cleaned") } } @@ -641,7 +636,7 @@ func TestTerminatedProcess_Event_LinkAndMonitor(t *testing.T) { time.Sleep(20 * time.Millisecond) // Counter = 2 (link + monitor) - entry := tm.events[event] + entry := tm.getEventEntry(event) if entry.subscriberCount != 2 { t.Errorf("subscriberCount should be 2, got %d", entry.subscriberCount) } @@ -664,14 +659,12 @@ func TestTerminatedProcess_Event_LinkAndMonitor(t *testing.T) { } // Verify linkRelations cleaned for consumer - linkKey := relationKey{consumer: consumer, target: event} - if _, exists := tm.linkRelations[linkKey]; exists { + if exists := tm.hasLinkRelation(consumer, event); exists { t.Error("Link should be removed") } // Verify monitorRelations cleaned for consumer - monitorKey := relationKey{consumer: consumer, target: event} - if _, exists := tm.monitorRelations[monitorKey]; exists { + if exists := tm.hasMonitorRelation(consumer, event); exists { t.Error("Monitor should be removed") } } @@ -705,12 +698,12 @@ func TestTerminatedEvent_LinkSubscribers(t *testing.T) { } // Event removed from tm.events - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed") } // Subscriptions cleaned - if len(tm.linkRelations) != 0 { + if tm.totalLinks() != 0 { t.Error("linkRelations should be empty") } } @@ -744,7 +737,7 @@ func TestTerminatedEvent_MonitorSubscribers(t *testing.T) { } // Cleaned - if len(tm.monitorRelations) != 0 { + if tm.totalMonitors() != 0 { t.Error("monitorRelations should be empty") } } @@ -783,18 +776,18 @@ func TestTerminatedEvent_Mixed(t *testing.T) { } // Event removed - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed") } // Verify linkRelations cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("linkRelations should be empty, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("linkRelations should be empty, got %d", tm.totalLinks()) } // Verify monitorRelations cleaned - if len(tm.monitorRelations) != 0 { - t.Errorf("monitorRelations should be empty, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("monitorRelations should be empty, got %d", tm.totalMonitors()) } } @@ -822,7 +815,7 @@ func TestTerminatedEvent_NoSubscribers(t *testing.T) { } // Event still removed - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed") } } @@ -840,9 +833,9 @@ func TestTerminatedTargetPID_RemoteCorePIDSubscriber(t *testing.T) { tm.LinkPID(localConsumer, target) // Simulate remote CorePID also linked (from node2) - key := relationKey{consumer: remoteCorePID, target: target} - tm.linkRelations[key] = struct{}{} - entry := tm.targetIndex[target] + s := tm.shardFor(target) + s.linkRelations[relationKey{consumer: remoteCorePID, target: target}] = struct{}{} + entry := tm.getTargetEntry(target) if entry != nil { entry.consumers[remoteCorePID] = struct{}{} } @@ -860,12 +853,12 @@ func TestTerminatedTargetPID_RemoteCorePIDSubscriber(t *testing.T) { } // Both links cleaned - if len(tm.linkRelations) != 0 { + if tm.totalLinks() != 0 { t.Error("All links should be cleaned") } // Verify targetIndex cleaned - if _, exists := tm.targetIndex[target]; exists { + if tm.getTargetEntry(target) != nil { t.Error("targetIndex should be cleaned") } } @@ -901,12 +894,12 @@ func TestTerminatedProcess_ProducerCleanup_LinkSubscribers(t *testing.T) { } // Event removed - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed after producer terminates") } // producerEvents index cleaned - if tm.producerEvents[producer] != nil { + if tm.getProducerEventsMap(producer) != nil { t.Error("producerEvents index should be cleaned") } } @@ -942,17 +935,17 @@ func TestTerminatedProcess_ProducerCleanup_MonitorSubscribers(t *testing.T) { } // Event removed - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed after producer terminates") } // Verify monitorRelations cleaned - if len(tm.monitorRelations) != 0 { - t.Errorf("monitorRelations should be empty, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 0 { + t.Errorf("monitorRelations should be empty, got %d", tm.totalMonitors()) } // Verify producerEvents cleaned - if tm.producerEvents[producer] != nil { + if tm.getProducerEventsMap(producer) != nil { t.Error("producerEvents index should be cleaned") } } @@ -992,18 +985,18 @@ func TestTerminatedProcess_ProducerCleanup_MultipleEvents(t *testing.T) { } // All events removed - if len(tm.events) != 0 { - t.Errorf("All events should be removed, got %d", len(tm.events)) + if tm.totalEvents() != 0 { + t.Errorf("All events should be removed, got %d", tm.totalEvents()) } // producerEvents index cleaned - if tm.producerEvents[producer] != nil { + if tm.getProducerEventsMap(producer) != nil { t.Error("producerEvents index should be cleaned") } // Verify linkRelations cleaned - if len(tm.linkRelations) != 0 { - t.Errorf("linkRelations should be empty, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 0 { + t.Errorf("linkRelations should be empty, got %d", tm.totalLinks()) } } @@ -1024,11 +1017,11 @@ func TestTerminatedProcess_ProducerCleanup_RelationsCleaned(t *testing.T) { tm.MonitorEvent(consumer, event) // Verify relations exist - if len(tm.linkRelations) != 1 { - t.Fatalf("Expected 1 link relation, got %d", len(tm.linkRelations)) + if tm.totalLinks() != 1 { + t.Fatalf("Expected 1 link relation, got %d", tm.totalLinks()) } - if len(tm.monitorRelations) != 1 { - t.Fatalf("Expected 1 monitor relation, got %d", len(tm.monitorRelations)) + if tm.totalMonitors() != 1 { + t.Fatalf("Expected 1 monitor relation, got %d", tm.totalMonitors()) } // Producer terminates @@ -1037,15 +1030,11 @@ func TestTerminatedProcess_ProducerCleanup_RelationsCleaned(t *testing.T) { time.Sleep(50 * time.Millisecond) // Relations for the event should be cleaned - for key := range tm.linkRelations { - if key.target == event { - t.Error("Link relation for event should be cleaned") - } + if exists := tm.hasLinkRelation(consumer, event); exists { + t.Error("Link relation for event should be cleaned") } - for key := range tm.monitorRelations { - if key.target == event { - t.Error("Monitor relation for event should be cleaned") - } + if exists := tm.hasMonitorRelation(consumer, event); exists { + t.Error("Monitor relation for event should be cleaned") } } @@ -1086,7 +1075,7 @@ func TestTerminatedProcess_ProducerCleanup_RemoteSubscribers(t *testing.T) { tm.LinkEvent(localConsumer, event) // Simulate remote subscriber (as if from node2 via network) - entry := tm.events[event] + entry := tm.getEventEntry(event) entry.linkSubscribersIndex[remoteConsumer] = len(entry.linkSubscribers) entry.linkSubscribers = append(entry.linkSubscribers, remoteConsumer) @@ -1103,7 +1092,7 @@ func TestTerminatedProcess_ProducerCleanup_RemoteSubscribers(t *testing.T) { } // Event removed - if _, exists := tm.events[event]; exists { + if tm.getEventEntry(event) != nil { t.Error("Event should be removed") } } From 91cf8580281eaed714d73e385ab3d1994d511f6d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 18 Mar 2026 10:39:57 +0100 Subject: [PATCH 053/122] fixes --- app/system/inspect/inspect.go | 3 +- app/system/inspect/message.go | 9 +++- app/system/inspect/process_list.go | 81 ++++++++++++++++++------------ gen/node.go | 2 +- node/node.go | 24 +++++---- testing/unit/node.go | 2 +- 6 files changed, 73 insertions(+), 48 deletions(-) diff --git a/app/system/inspect/inspect.go b/app/system/inspect/inspect.go index bb2b8180b..b06066e58 100644 --- a/app/system/inspect/inspect.go +++ b/app/system/inspect/inspect.go @@ -166,7 +166,8 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error r.Limit = 1000 } pname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, r.Start, r.Start+r.Limit-1)) - _, err := i.SpawnRegister(pname, factory_process_list, opts, r.Start, r.Limit) + _, err := i.SpawnRegister(pname, factory_process_list, opts, + r.Start, r.Limit, r.Name, r.Behavior, r.Application, r.State, r.MinMailbox) if err != nil && err != gen.ErrTaken { return err, nil } diff --git a/app/system/inspect/message.go b/app/system/inspect/message.go index cc7f8e895..67e94b7aa 100644 --- a/app/system/inspect/message.go +++ b/app/system/inspect/message.go @@ -67,8 +67,13 @@ type MessageInspectConnectionList struct { // process list type RequestInspectProcessList struct { - Start int - Limit int + Start int + Limit int + Name string + Behavior string + Application string + State string + MinMailbox uint64 } type ResponseInspectProcessList struct { Event gen.Event diff --git a/app/system/inspect/process_list.go b/app/system/inspect/process_list.go index 7798a5990..ab640179b 100644 --- a/app/system/inspect/process_list.go +++ b/app/system/inspect/process_list.go @@ -3,6 +3,7 @@ package inspect import ( "fmt" "slices" + "strings" "ergo.services/ergo/act" "ergo.services/ergo/gen" @@ -16,8 +17,14 @@ type process_list struct { act.Actor token gen.Ref - start int - limit int + start int + limit int + name string + behavior string + application string + state string + minMailbox uint64 + generating bool loopID uint64 event gen.Atom @@ -26,45 +33,33 @@ type process_list struct { func (ipl *process_list) Init(args ...any) error { ipl.start = args[0].(int) ipl.limit = args[1].(int) + ipl.name = args[2].(string) + ipl.behavior = args[3].(string) + ipl.application = args[4].(string) + ipl.state = args[5].(string) + ipl.minMailbox = args[6].(uint64) + ipl.Log().SetLogger("default") ipl.Log().Debug("process list inspector started. %d...%d", ipl.start, ipl.start+ipl.limit-1) - // RegisterEvent is not allowed here ipl.Send(ipl.PID(), register{}) return nil } + func (ipl *process_list) HandleMessage(from gen.PID, message any) error { switch m := message.(type) { case generate: if m.id != ipl.loopID || ipl.generating == false { ipl.Log().Debug("generating canceled") - break // cancelled + break } ipl.Log().Debug("generating event") - start := ipl.start - if start < 0 { - // negative start means "last N": find the highest PID and work backwards - pids, err := ipl.Node().ProcessList() - if err != nil { - return err - } - if len(pids) > 0 { - // PIDs are not necessarily sorted, find max ID - maxID := uint64(0) - for _, p := range pids { - if p.ID > maxID { - maxID = p.ID - } - } - start = int(maxID) - ipl.limit - if start < 1000 { - start = 1000 - } - } else { - start = 1000 - } + var filter []func(gen.ProcessShortInfo) bool + if ipl.hasFilters() { + filter = append(filter, ipl.matchFilter) } - list, err := ipl.Node().ProcessListShortInfo(start, ipl.limit) + + list, err := ipl.Node().ProcessListShortInfo(ipl.start, ipl.limit, filter...) if err != nil { return err } @@ -98,7 +93,7 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { case register: eopts := gen.EventOptions{ Notify: true, - Buffer: 1, // keep the last event + Buffer: 1, } evname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, ipl.start, ipl.start+ipl.limit-1)) token, err := ipl.RegisterEvent(evname, eopts) @@ -108,24 +103,23 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { } ipl.Log().Info("registered event %s", evname) ipl.event = evname - ipl.token = token ipl.SendAfter(ipl.PID(), shutdown{}, inspectProcessListIdlePeriod) case shutdown: if ipl.generating { ipl.Log().Debug("ignore shutdown. generating is active") - break // ignore. + break } return gen.TerminateReasonNormal - case gen.MessageEventStart: // got first subscriber + case gen.MessageEventStart: ipl.Log().Debug("got first subscriber. start generating events...") ipl.loopID++ ipl.Send(ipl.PID(), generate{id: ipl.loopID}) ipl.generating = true - case gen.MessageEventStop: // no subscribers + case gen.MessageEventStop: ipl.Log().Debug("no subscribers. stop generating") if ipl.generating { ipl.generating = false @@ -142,3 +136,26 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { func (ipl *process_list) Terminate(reason error) { ipl.Log().Debug("process list inspector terminated: %s", reason) } + +func (ipl *process_list) hasFilters() bool { + return ipl.name != "" || ipl.behavior != "" || ipl.application != "" || ipl.state != "" || ipl.minMailbox > 0 +} + +func (ipl *process_list) matchFilter(info gen.ProcessShortInfo) bool { + if ipl.name != "" && strings.Contains(strings.ToLower(string(info.Name)), strings.ToLower(ipl.name)) == false { + return false + } + if ipl.behavior != "" && strings.Contains(strings.ToLower(info.Behavior), strings.ToLower(ipl.behavior)) == false { + return false + } + if ipl.application != "" && strings.Contains(strings.ToLower(string(info.Application)), strings.ToLower(ipl.application)) == false { + return false + } + if ipl.state != "" && strings.EqualFold(info.State.String(), ipl.state) == false { + return false + } + if ipl.minMailbox > 0 && info.MessagesMailbox < ipl.minMailbox { + return false + } + return true +} diff --git a/gen/node.go b/gen/node.go index 121b7b13e..f3919b29f 100644 --- a/gen/node.go +++ b/gen/node.go @@ -106,7 +106,7 @@ type Node interface { // More efficient than ProcessList + ProcessInfo for each. // Available in: Running state only. // Returns ErrNodeTerminated in other states. - ProcessListShortInfo(start, limit int) ([]ProcessShortInfo, error) + ProcessListShortInfo(start, limit int, filter ...func(ProcessShortInfo) bool) ([]ProcessShortInfo, error) // ProcessRangeShortInfo iterates over all processes calling fn for each. // The callback receives ProcessShortInfo and returns true to continue diff --git a/node/node.go b/node/node.go index a1d8bc13b..71df49dd1 100644 --- a/node/node.go +++ b/node/node.go @@ -881,29 +881,28 @@ func (n *node) ProcessList() ([]gen.PID, error) { return pl, nil } -func (n *node) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortInfo, error) { +func (n *node) ProcessListShortInfo(start, limit int, filter ...func(gen.ProcessShortInfo) bool) ([]gen.ProcessShortInfo, error) { if n.isRunning() == false { return nil, gen.ErrNodeTerminated } - if start < 1000 || limit < 0 { + if limit < 0 || (start >= 0 && start < 1000) { return nil, gen.ErrIncorrect } if limit == 0 { limit = 100 } - ustart := uint64(start) - psi := []gen.ProcessShortInfo{} - pid := n.corePID - for limit > 0 { + from, to, step := int64(start), int64(n.nextID)+1, int64(1) + if start < 0 { + from, to, step = int64(n.nextID), 999, -1 + } - if ustart > n.nextID { - break - } + psi := []gen.ProcessShortInfo{} + pid := n.corePID - pid.ID = ustart - ustart++ + for id := from; id != to && limit > 0; id += step { + pid.ID = uint64(id) v, found := n.processes.Load(pid) if found == false { continue @@ -930,6 +929,9 @@ func (n *node) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortInfo, e Leader: process.leader, LogLevel: process.log.Level(), } + if len(filter) > 0 && filter[0](info) == false { + continue + } psi = append(psi, info) limit-- } diff --git a/testing/unit/node.go b/testing/unit/node.go index 127409177..6d5c79c72 100644 --- a/testing/unit/node.go +++ b/testing/unit/node.go @@ -230,7 +230,7 @@ func (tn *TestNode) ProcessList() ([]gen.PID, error) { return pids, nil } -func (tn *TestNode) ProcessListShortInfo(start, limit int) ([]gen.ProcessShortInfo, error) { +func (tn *TestNode) ProcessListShortInfo(start, limit int, filter ...func(gen.ProcessShortInfo) bool) ([]gen.ProcessShortInfo, error) { var infos []gen.ProcessShortInfo for pid := range tn.processes { infos = append(infos, gen.ProcessShortInfo{ From 90d307d6570ee3dde6b6ee832931797a297f3a14 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 09:50:47 +0100 Subject: [PATCH 054/122] improve system app --- app/system/inspect/application_tree.go | 1 + app/system/inspect/connection_list.go | 1 + app/system/inspect/event_list.go | 1 + app/system/inspect/goroutines.go | 169 +++++++++++++++++++++ app/system/inspect/heap.go | 62 ++++++++ app/system/inspect/heap_inspector.go | 202 +++++++++++++++++++++++++ app/system/inspect/inspect.go | 41 +++++ app/system/inspect/log.go | 1 + app/system/inspect/message.go | 83 ++++++++++ app/system/inspect/process_list.go | 1 + app/system/inspect/process_range.go | 1 + lib/compress.go | 22 ++- net/edf/init.go | 12 ++ 13 files changed, 591 insertions(+), 6 deletions(-) create mode 100644 app/system/inspect/goroutines.go create mode 100644 app/system/inspect/heap.go create mode 100644 app/system/inspect/heap_inspector.go diff --git a/app/system/inspect/application_tree.go b/app/system/inspect/application_tree.go index 04f62a0d4..8b761ddb6 100644 --- a/app/system/inspect/application_tree.go +++ b/app/system/inspect/application_tree.go @@ -29,6 +29,7 @@ func (iat *application_tree) Init(args ...any) error { iat.Log().Debug("application tree inspector started for %s with limit %d", iat.application, iat.limit) // RegisterEvent is not allowed here iat.Send(iat.PID(), register{}) + iat.SetCompression(true) return nil } diff --git a/app/system/inspect/connection_list.go b/app/system/inspect/connection_list.go index 507014bd9..be1fb01e6 100644 --- a/app/system/inspect/connection_list.go +++ b/app/system/inspect/connection_list.go @@ -33,6 +33,7 @@ func (icl *connection_list) Init(args ...any) error { icl.Log().SetLogger("default") icl.Log().Debug("connection list inspector started. name=%q limit=%d", icl.name, icl.limit) icl.Send(icl.PID(), register{}) + icl.SetCompression(true) return nil } diff --git a/app/system/inspect/event_list.go b/app/system/inspect/event_list.go index 888f9d722..6a7ab9b7a 100644 --- a/app/system/inspect/event_list.go +++ b/app/system/inspect/event_list.go @@ -40,6 +40,7 @@ func (iel *event_list) Init(args ...any) error { iel.Log().Debug("event list inspector started. name=%q notify=%d buffered=%d minSubs=%d limit=%d", iel.name, iel.notify, iel.buffered, iel.minSubscribers, iel.limit) iel.Send(iel.PID(), register{}) + iel.SetCompression(true) return nil } diff --git a/app/system/inspect/goroutines.go b/app/system/inspect/goroutines.go new file mode 100644 index 000000000..f427204f2 --- /dev/null +++ b/app/system/inspect/goroutines.go @@ -0,0 +1,169 @@ +package inspect + +import ( + "runtime" + "sort" + "strconv" + "strings" +) + +func captureGoroutines(req RequestDoGoroutines) ResponseDoGoroutines { + buf := make([]byte, 1<<20) + for { + n := runtime.Stack(buf, true) + if n < len(buf) { + buf = buf[:n] + break + } + buf = make([]byte, len(buf)*2) + } + + blocks := strings.Split(string(buf), "\n\n") + + stackFilter := strings.ToLower(req.Stack) + stateFilter := strings.ToLower(req.State) + + type parsed struct { + id int + state string + waitSec int64 + frames string + top string + bottom string + full string + } + + var matched []parsed + total := 0 + + for _, block := range blocks { + block = strings.TrimSpace(block) + if strings.HasPrefix(block, "goroutine ") == false { + continue + } + total++ + + id, state, waitSec := parseHeader(block) + + if stateFilter != "" && strings.ToLower(state) != stateFilter { + continue + } + if req.MinWait > 0 && waitSec < req.MinWait { + continue + } + if stackFilter != "" && strings.Contains(strings.ToLower(block), stackFilter) == false { + continue + } + + funcs := parseFuncLines(block) + top := "" + bottom := "" + if len(funcs) > 0 { + top = funcs[0] + bottom = funcs[len(funcs)-1] + } + + matched = append(matched, parsed{ + id: id, + state: state, + waitSec: waitSec, + frames: state + "|" + strings.Join(funcs, "|"), + top: top, + bottom: bottom, + full: block, + }) + } + + // group by identical stack + groupMap := make(map[string]*GoroutineGroup) + var order []string + + for _, p := range matched { + g, ok := groupMap[p.frames] + if ok == false { + g = &GoroutineGroup{State: p.state, WaitSec: p.waitSec, Current: p.top, Origin: p.bottom, Stack: p.full} + groupMap[p.frames] = g + order = append(order, p.frames) + } + g.Count++ + g.IDs = append(g.IDs, p.id) + } + + groups := make([]GoroutineGroup, 0, len(order)) + for _, key := range order { + groups = append(groups, *groupMap[key]) + } + + sort.Slice(groups, func(i, j int) bool { + return groups[i].Count > groups[j].Count + }) + + return ResponseDoGoroutines{ + Groups: groups, + Total: total, + Filtered: len(matched), + } +} + +func parseHeader(block string) (id int, state string, waitSec int64) { + lines := strings.SplitN(block, "\n", 2) + header := lines[0] + + rest := header[len("goroutine "):] + spaceIdx := strings.IndexByte(rest, ' ') + if spaceIdx < 0 { + return + } + id, _ = strconv.Atoi(rest[:spaceIdx]) + + open := strings.IndexByte(rest, '[') + close := strings.IndexByte(rest, ']') + if open < 0 || close <= open { + return + } + + stateStr := rest[open+1 : close] + parts := strings.SplitN(stateStr, ",", 2) + state = strings.TrimSpace(parts[0]) + + if len(parts) > 1 { + waitSec = parseWaitDuration(strings.TrimSpace(parts[1])) + } + return +} + +func parseWaitDuration(s string) int64 { + // "5 minutes", "847 minutes", "2 hours" + parts := strings.Fields(s) + if len(parts) < 2 { + return 0 + } + n, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil { + return 0 + } + unit := strings.TrimSuffix(parts[1], "s") // "minute" from "minutes" + switch unit { + case "minute": + return n * 60 + case "hour": + return n * 3600 + case "second": + return n + } + return 0 +} + +func parseFuncLines(block string) []string { + lines := strings.Split(block, "\n") + var funcs []string + for i := 1; i < len(lines); i++ { + if len(lines[i]) > 0 && lines[i][0] != '\t' { + f := strings.TrimSpace(lines[i]) + if f != "" { + funcs = append(funcs, f) + } + } + } + return funcs +} diff --git a/app/system/inspect/heap.go b/app/system/inspect/heap.go new file mode 100644 index 000000000..818ce4ef2 --- /dev/null +++ b/app/system/inspect/heap.go @@ -0,0 +1,62 @@ +package inspect + +import ( + "runtime" + "sort" +) + +func captureHeapProfile(req RequestDoHeapProfile) ResponseDoHeapProfile { + // force up-to-date stats + runtime.GC() + + var p []runtime.MemProfileRecord + n, _ := runtime.MemProfile(nil, true) + p = make([]runtime.MemProfileRecord, n) + runtime.MemProfile(p, true) + + var records []HeapRecord + var totalInuse, totalAlloc, totalObjects int64 + + for _, r := range p { + inuse := r.InUseBytes() + if req.MinBytes > 0 && inuse < req.MinBytes { + continue + } + + frames := runtime.CallersFrames(r.Stack()) + var stack []string + for { + frame, more := frames.Next() + if frame.Function != "" { + stack = append(stack, frame.Function) + } + if more == false { + break + } + } + + rec := HeapRecord{ + InuseBytes: inuse, + InuseObjects: r.InUseObjects(), + AllocBytes: r.AllocBytes, + AllocObjects: r.AllocObjects, + Stack: stack, + } + records = append(records, rec) + + totalInuse += inuse + totalAlloc += r.AllocBytes + totalObjects += r.InUseObjects() + } + + sort.Slice(records, func(i, j int) bool { + return records[i].InuseBytes > records[j].InuseBytes + }) + + return ResponseDoHeapProfile{ + Records: records, + TotalInuse: totalInuse, + TotalAlloc: totalAlloc, + TotalObjects: totalObjects, + } +} diff --git a/app/system/inspect/heap_inspector.go b/app/system/inspect/heap_inspector.go new file mode 100644 index 000000000..cfcb8b31e --- /dev/null +++ b/app/system/inspect/heap_inspector.go @@ -0,0 +1,202 @@ +package inspect + +import ( + "fmt" + "runtime" + "sort" + "strings" + + "ergo.services/ergo/act" + "ergo.services/ergo/gen" +) + +func factory_heap() gen.ProcessBehavior { + return &heap_inspector{} +} + +type heap_inspector struct { + act.Actor + token gen.Ref + + limit int + name string + + generating bool + loopID uint64 + event gen.Atom +} + +func (h *heap_inspector) Init(args ...any) error { + h.limit = args[0].(int) + h.name = args[1].(string) + + h.Log().SetLogger("default") + h.Send(h.PID(), register{}) + h.SetCompression(true) + return nil +} + +func (h *heap_inspector) HandleMessage(from gen.PID, message any) error { + switch m := message.(type) { + case generate: + if m.id != h.loopID || h.generating == false { + break + } + + records, totalAlloc, totalFree := h.captureTop() + + var totalInuse, totalObjects int64 + for _, r := range records { + totalInuse += r.InuseBytes + totalObjects += r.InuseObjects + } + + var ms runtime.MemStats + runtime.ReadMemStats(&ms) + + ev := MessageInspectHeap{ + Node: h.Node().Name(), + Records: records, + TotalInuse: totalInuse, + TotalObjects: totalObjects, + TotalAlloc: totalAlloc, + TotalFree: totalFree, + GCCPUFraction: ms.GCCPUFraction, + } + + if err := h.SendEvent(h.event, h.token, ev); err != nil { + h.Log().Error("unable to send event %q: %s", h.event, err) + return gen.TerminateReasonNormal + } + + h.SendAfter(h.PID(), generate{id: h.loopID}, inspectHeapPeriod) + + case requestInspect: + response := ResponseInspectHeap{ + Event: gen.Event{ + Name: h.event, + Node: h.Node().Name(), + }, + } + h.SendResponse(m.pid, m.ref, response) + + case register: + eopts := gen.EventOptions{Notify: true, Buffer: 1} + hash := filterHash(h.name, "", "", "", 0, h.limit) + h.event = gen.Atom(fmt.Sprintf("%s_%s", inspectHeap, hash)) + token, err := h.RegisterEvent(h.event, eopts) + if err != nil { + h.Log().Error("unable to register event: %s", err) + return err + } + h.token = token + h.SendAfter(h.PID(), shutdown{}, inspectHeapIdlePeriod) + + case shutdown: + if h.generating { + break + } + return gen.TerminateReasonNormal + + case gen.MessageEventStart: + h.loopID++ + h.Send(h.PID(), generate{id: h.loopID}) + h.generating = true + + case gen.MessageEventStop: + if h.generating { + h.generating = false + h.SendAfter(h.PID(), shutdown{}, inspectHeapIdlePeriod) + } + } + + return nil +} + +func (h *heap_inspector) Terminate(reason error) {} + +func (h *heap_inspector) captureTop() ([]HeapRecord, int64, int64) { + var p []runtime.MemProfileRecord + n, _ := runtime.MemProfile(nil, false) // false = include freed records + p = make([]runtime.MemProfileRecord, n) + runtime.MemProfile(p, false) + + nameLower := strings.ToLower(h.name) + + type entry struct { + inuse int64 + objects int64 + alloc int64 + allocN int64 + freeN int64 + stack []string + } + + var entries []entry + var totalAlloc, totalFree int64 + + for _, r := range p { + totalAlloc += r.AllocObjects + totalFree += r.FreeObjects + + inuse := r.InUseBytes() + if inuse <= 0 { + continue + } + + frames := runtime.CallersFrames(r.Stack()) + var stack []string + for { + frame, more := frames.Next() + if frame.Function != "" { + stack = append(stack, frame.Function) + } + if more == false { + break + } + } + + if nameLower != "" { + matched := false + for _, f := range stack { + if strings.Contains(strings.ToLower(f), nameLower) { + matched = true + break + } + } + if matched == false { + continue + } + } + + entries = append(entries, entry{ + inuse: inuse, + objects: r.InUseObjects(), + alloc: r.AllocBytes, + allocN: r.AllocObjects, + freeN: r.FreeObjects, + stack: stack, + }) + } + + sort.Slice(entries, func(i, j int) bool { + return entries[i].inuse > entries[j].inuse + }) + + if len(entries) > h.limit { + entries = entries[:h.limit] + } + + records := make([]HeapRecord, len(entries)) + for i, e := range entries { + records[i] = HeapRecord{ + InuseBytes: e.inuse, + InuseObjects: e.objects, + AllocBytes: e.alloc, + AllocObjects: e.allocN, + FreeObjects: e.freeN, + Stack: e.stack, + } + } + return records, totalAlloc, totalFree +} diff --git a/app/system/inspect/inspect.go b/app/system/inspect/inspect.go index b06066e58..42deb1c18 100644 --- a/app/system/inspect/inspect.go +++ b/app/system/inspect/inspect.go @@ -67,6 +67,10 @@ const ( inspectConnectionList = "inspect_connection_list" inspectConnectionListPeriod = time.Second inspectConnectionListIdlePeriod = 5 * time.Second + + inspectHeap = "inspect_heap" + inspectHeapPeriod = time.Second + inspectHeapIdlePeriod = 5 * time.Second ) var ( @@ -80,9 +84,24 @@ var ( ) func Factory() gen.ProcessBehavior { + return &inspectPool{} +} + +func workerFactory() gen.ProcessBehavior { return &inspect{} } +type inspectPool struct { + act.Pool +} + +func (p *inspectPool) Init(args ...any) (act.PoolOptions, error) { + return act.PoolOptions{ + PoolSize: 5, + WorkerFactory: workerFactory, + }, nil +} + type inspect struct { act.Actor } @@ -100,6 +119,7 @@ type flushLog struct{ id uint64 } func (i *inspect) Init(args ...any) error { i.Log().SetLogger("default") i.Log().Debug("%s started", i.Name()) + i.SetCompression(true) return nil } @@ -403,6 +423,21 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error i.Send(pname, forward) return nil, nil // no reply + case RequestInspectHeap: + opts := gen.ProcessOptions{LinkParent: true} + if r.Limit < 1 { + r.Limit = 100 + } + hash := filterHash(r.Name, "", "", "", 0, r.Limit) + pname := gen.Atom(fmt.Sprintf("%s_%s", inspectHeap, hash)) + _, err := i.SpawnRegister(pname, factory_heap, opts, r.Limit, r.Name) + if err != nil && err != gen.ErrTaken { + return err, nil + } + forward := requestInspect{pid: from, ref: ref} + i.Send(pname, forward) + return nil, nil + // do commands case RequestDoSend: @@ -515,6 +550,12 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error case RequestDoInspect: state, err := i.Inspect(r.PID) return ResponseDoInspect{State: state, Error: err}, nil + + case RequestDoGoroutines: + return captureGoroutines(r), nil + + case RequestDoHeapProfile: + return captureHeapProfile(r), nil } i.Log().Error("unsupported request: %#v", request) diff --git a/app/system/inspect/log.go b/app/system/inspect/log.go index 76157112d..2395ba572 100644 --- a/app/system/inspect/log.go +++ b/app/system/inspect/log.go @@ -38,6 +38,7 @@ func (il *log) Init(args ...any) error { il.Log().SetLogger("default") il.Log().Debug("log inspector started (limit: %d)", il.limit) il.Send(il.PID(), register{}) + il.SetCompression(true) return nil } diff --git a/app/system/inspect/message.go b/app/system/inspect/message.go index 67e94b7aa..6b57c888c 100644 --- a/app/system/inspect/message.go +++ b/app/system/inspect/message.go @@ -324,6 +324,89 @@ type ResponseDoInspect struct { Error error } +// goroutine dump + +type RequestDoGoroutines struct { + Stack string // substring match in stack text + State string // exact state match (running, chan receive, etc.) + MinWait int64 // minimum wait duration in seconds (0 = any) +} + +type GoroutineInfo struct { + ID int + State string + Wait string + Frames []string + FullText string +} + +type GoroutineGroup struct { + Count int + State string + WaitSec int64 + Origin string + Current string + Stack string + IDs []int +} + +type ResponseDoGoroutines struct { + Groups []GoroutineGroup + Total int + Filtered int + Error error +} + +// heap profile + +type RequestDoHeapProfile struct { + MinBytes int64 +} + +type HeapRecord struct { + InuseBytes int64 + InuseObjects int64 + AllocBytes int64 + AllocObjects int64 + FreeObjects int64 + Stack []string +} + +type HeapStats struct { + TotalInuse int64 + TotalObjects int64 + TotalAlloc int64 + TotalFree int64 +} + +type ResponseDoHeapProfile struct { + Records []HeapRecord + TotalInuse int64 + TotalAlloc int64 + TotalObjects int64 + Error error +} + +// heap inspector (event-based) + +type RequestInspectHeap struct { + Limit int + Name string +} +type ResponseInspectHeap struct { + Event gen.Event +} + +type MessageInspectHeap struct { + Node gen.Atom + Records []HeapRecord + TotalInuse int64 + TotalObjects int64 + TotalAlloc int64 + TotalFree int64 + GCCPUFraction float64 +} + // process range (full scan with filters) type RequestInspectProcessRange struct { diff --git a/app/system/inspect/process_list.go b/app/system/inspect/process_list.go index ab640179b..2a8608734 100644 --- a/app/system/inspect/process_list.go +++ b/app/system/inspect/process_list.go @@ -42,6 +42,7 @@ func (ipl *process_list) Init(args ...any) error { ipl.Log().SetLogger("default") ipl.Log().Debug("process list inspector started. %d...%d", ipl.start, ipl.start+ipl.limit-1) ipl.Send(ipl.PID(), register{}) + ipl.SetCompression(true) return nil } diff --git a/app/system/inspect/process_range.go b/app/system/inspect/process_range.go index 869446971..7db7c1aa5 100644 --- a/app/system/inspect/process_range.go +++ b/app/system/inspect/process_range.go @@ -43,6 +43,7 @@ func (ipr *process_range) Init(args ...any) error { ipr.Log().Debug("process range inspector started. name=%q behavior=%q app=%q state=%q mailbox>=%d limit=%d", ipr.name, ipr.behavior, ipr.application, ipr.state, ipr.minMailbox, ipr.limit) ipr.Send(ipr.PID(), register{}) + ipr.SetCompression(true) return nil } diff --git a/lib/compress.go b/lib/compress.go index e6bd1db9a..ebd594d7f 100644 --- a/lib/compress.go +++ b/lib/compress.go @@ -15,6 +15,7 @@ import ( var ( gzipWriters [3]*sync.Pool + zlibWriters *sync.Pool gzipReaders = &sync.Pool{ New: func() any { return nil @@ -50,11 +51,14 @@ func CompressZLIB(src *Buffer, preallocate uint) (dst *Buffer, err error) { zBuffer.Allocate(int(preallocate) + 4) binary.BigEndian.PutUint32(zBuffer.B[preallocate:], uint32(src.Len())) - zWriter := zlib.NewWriter(zBuffer) - if _, err := zWriter.Write(src.B); err != nil { + zWriter := zlibWriters.Get().(*zlib.Writer) + zWriter.Reset(zBuffer) + _, err = zWriter.Write(src.B) + zWriter.Close() + zlibWriters.Put(zWriter) + if err != nil { return nil, err } - zWriter.Close() return zBuffer, nil } @@ -86,11 +90,12 @@ func CompressGZIP(src *Buffer, preallocate uint, level int) (dst *Buffer, err er } else { zWriter, _ = gzip.NewWriterLevel(zBuffer, lev) } - if _, err := zWriter.Write(src.B); err != nil { - return nil, err - } + _, err = zWriter.Write(src.B) zWriter.Close() gzipWriters[level].Put(zWriter) + if err != nil { + return nil, err + } return zBuffer, nil } @@ -183,4 +188,9 @@ func init() { }, } } + zlibWriters = &sync.Pool{ + New: func() any { + return zlib.NewWriter(io.Discard) + }, + } } diff --git a/net/edf/init.go b/net/edf/init.go index 29486d30f..cb1c207d7 100644 --- a/net/edf/init.go +++ b/net/edf/init.go @@ -162,6 +162,18 @@ var ( inspect.RequestInspectApplicationTree{}, inspect.ResponseInspectApplicationTree{}, inspect.MessageInspectApplicationTree{}, + + inspect.RequestDoGoroutines{}, + inspect.GoroutineGroup{}, + inspect.ResponseDoGoroutines{}, + + inspect.RequestDoHeapProfile{}, + inspect.HeapRecord{}, + inspect.ResponseDoHeapProfile{}, + + inspect.RequestInspectHeap{}, + inspect.ResponseInspectHeap{}, + inspect.MessageInspectHeap{}, } // register standard errors of the Ergo Framework From 53a6609605dc7fd0528d130823069f7cd9c59be4 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 10:00:54 +0100 Subject: [PATCH 055/122] improve system app --- app/system/inspect/application_list.go | 35 ++++++++++++-------------- app/system/inspect/application_tree.go | 35 ++++++++++++-------------- app/system/inspect/connection.go | 35 ++++++++++++-------------- app/system/inspect/connection_list.go | 31 +++++++++++------------ app/system/inspect/event_list.go | 31 +++++++++++------------ app/system/inspect/heap_inspector.go | 25 +++++++++--------- app/system/inspect/log.go | 29 +++++++++++---------- app/system/inspect/meta.go | 35 ++++++++++++-------------- app/system/inspect/meta_state.go | 35 ++++++++++++-------------- app/system/inspect/network.go | 31 +++++++++++------------ app/system/inspect/node.go | 31 +++++++++++------------ app/system/inspect/process.go | 35 ++++++++++++-------------- app/system/inspect/process_list.go | 33 ++++++++++++------------ app/system/inspect/process_range.go | 31 +++++++++++------------ app/system/inspect/process_state.go | 35 ++++++++++++-------------- 15 files changed, 227 insertions(+), 260 deletions(-) diff --git a/app/system/inspect/application_list.go b/app/system/inspect/application_list.go index d07fb604c..cdcb91b08 100644 --- a/app/system/inspect/application_list.go +++ b/app/system/inspect/application_list.go @@ -23,8 +23,22 @@ type application_list struct { func (ial *application_list) Init(args ...any) error { ial.Log().SetLogger("default") ial.Log().Debug("application list inspector started") - // RegisterEvent is not allowed here - ial.Send(ial.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s", inspectApplicationList)) + token, err := ial.RegisterEvent(evname, eopts) + if err != nil { + ial.Log().Error("unable to register event: %s", err) + return err + } + ial.Log().Info("registered event %s", evname) + ial.event = evname + ial.token = token + ial.SendAfter(ial.PID(), shutdown{}, inspectApplicationListIdlePeriod) + return nil } @@ -73,23 +87,6 @@ func (ial *application_list) HandleMessage(from gen.PID, message any) error { ial.SendResponse(m.pid, m.ref, response) ial.Log().Debug("sent response for the inspect application list request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s", inspectApplicationList)) - token, err := ial.RegisterEvent(evname, eopts) - if err != nil { - ial.Log().Error("unable to register event: %s", err) - return err - } - ial.Log().Info("registered event %s", evname) - ial.event = evname - - ial.token = token - ial.SendAfter(ial.PID(), shutdown{}, inspectApplicationListIdlePeriod) - case shutdown: if ial.generating { ial.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/application_tree.go b/app/system/inspect/application_tree.go index 8b761ddb6..71ea803a0 100644 --- a/app/system/inspect/application_tree.go +++ b/app/system/inspect/application_tree.go @@ -27,9 +27,23 @@ func (iat *application_tree) Init(args ...any) error { iat.limit = args[1].(int) iat.Log().SetLogger("default") iat.Log().Debug("application tree inspector started for %s with limit %d", iat.application, iat.limit) - // RegisterEvent is not allowed here - iat.Send(iat.PID(), register{}) iat.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s_%d", inspectApplicationTree, iat.application, iat.limit)) + token, err := iat.RegisterEvent(evname, eopts) + if err != nil { + iat.Log().Error("unable to register event: %s", err) + return err + } + iat.Log().Info("registered event %s", evname) + iat.event = evname + iat.token = token + iat.SendAfter(iat.PID(), shutdown{}, inspectApplicationTreeIdlePeriod) + return nil } @@ -70,23 +84,6 @@ func (iat *application_tree) HandleMessage(from gen.PID, message any) error { iat.SendResponse(m.pid, m.ref, response) iat.Log().Debug("sent response for the inspect application tree request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s_%d", inspectApplicationTree, iat.application, iat.limit)) - token, err := iat.RegisterEvent(evname, eopts) - if err != nil { - iat.Log().Error("unable to register event: %s", err) - return err - } - iat.Log().Info("registered event %s", evname) - iat.event = evname - - iat.token = token - iat.SendAfter(iat.PID(), shutdown{}, inspectApplicationTreeIdlePeriod) - case shutdown: if iat.generating { iat.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/connection.go b/app/system/inspect/connection.go index 92f7dac84..60e7777fc 100644 --- a/app/system/inspect/connection.go +++ b/app/system/inspect/connection.go @@ -25,8 +25,22 @@ func (ic *connection) Init(args ...any) error { ic.remote = args[0].(gen.Atom) ic.Log().SetLogger("default") ic.Log().Debug("connection inspector started") - // RegisterEvent is not allowed here - ic.Send(ic.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s", inspectConnection, ic.remote)) + token, err := ic.RegisterEvent(evname, eopts) + if err != nil { + ic.Log().Error("unable to register connection event: %s", err) + return err + } + ic.Log().Info("registered event %s", inspectNetwork) + ic.event = evname + ic.token = token + ic.SendAfter(ic.PID(), shutdown{}, inspectNetworkIdlePeriod) + return nil } @@ -81,23 +95,6 @@ func (ic *connection) HandleMessage(from gen.PID, message any) error { return gen.TerminateReasonNormal } - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s", inspectConnection, ic.remote)) - token, err := ic.RegisterEvent(evname, eopts) - if err != nil { - ic.Log().Error("unable to register connection event: %s", err) - return err - } - ic.Log().Info("registered event %s", inspectNetwork) - ic.event = evname - - ic.token = token - ic.SendAfter(ic.PID(), shutdown{}, inspectNetworkIdlePeriod) - case shutdown: if ic.generating { ic.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/connection_list.go b/app/system/inspect/connection_list.go index be1fb01e6..63b455384 100644 --- a/app/system/inspect/connection_list.go +++ b/app/system/inspect/connection_list.go @@ -32,8 +32,22 @@ func (icl *connection_list) Init(args ...any) error { icl.Log().SetLogger("default") icl.Log().Debug("connection list inspector started. name=%q limit=%d", icl.name, icl.limit) - icl.Send(icl.PID(), register{}) icl.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + icl.event = gen.Atom(fmt.Sprintf("%s_%s", inspectConnectionList, icl.hash)) + token, err := icl.RegisterEvent(icl.event, eopts) + if err != nil { + icl.Log().Error("unable to register event: %s", err) + return err + } + icl.Log().Info("registered event %s", icl.event) + icl.token = token + icl.SendAfter(icl.PID(), shutdown{}, inspectConnectionListIdlePeriod) + return nil } @@ -95,21 +109,6 @@ func (icl *connection_list) HandleMessage(from gen.PID, message any) error { } icl.SendResponse(m.pid, m.ref, response) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, - } - icl.event = gen.Atom(fmt.Sprintf("%s_%s", inspectConnectionList, icl.hash)) - token, err := icl.RegisterEvent(icl.event, eopts) - if err != nil { - icl.Log().Error("unable to register event: %s", err) - return err - } - icl.Log().Info("registered event %s", icl.event) - icl.token = token - icl.SendAfter(icl.PID(), shutdown{}, inspectConnectionListIdlePeriod) - case shutdown: if icl.generating { break diff --git a/app/system/inspect/event_list.go b/app/system/inspect/event_list.go index 6a7ab9b7a..d276f2615 100644 --- a/app/system/inspect/event_list.go +++ b/app/system/inspect/event_list.go @@ -39,8 +39,22 @@ func (iel *event_list) Init(args ...any) error { iel.Log().SetLogger("default") iel.Log().Debug("event list inspector started. name=%q notify=%d buffered=%d minSubs=%d limit=%d", iel.name, iel.notify, iel.buffered, iel.minSubscribers, iel.limit) - iel.Send(iel.PID(), register{}) iel.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + iel.event = gen.Atom(fmt.Sprintf("%s_%s", inspectEventList, iel.hash)) + token, err := iel.RegisterEvent(iel.event, eopts) + if err != nil { + iel.Log().Error("unable to register event: %s", err) + return err + } + iel.Log().Info("registered event %s", iel.event) + iel.token = token + iel.SendAfter(iel.PID(), shutdown{}, inspectEventListIdlePeriod) + return nil } @@ -118,21 +132,6 @@ func (iel *event_list) HandleMessage(from gen.PID, message any) error { iel.SendResponse(m.pid, m.ref, response) iel.Log().Debug("sent response for the inspect event list request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, - } - iel.event = gen.Atom(fmt.Sprintf("%s_%s", inspectEventList, iel.hash)) - token, err := iel.RegisterEvent(iel.event, eopts) - if err != nil { - iel.Log().Error("unable to register event: %s", err) - return err - } - iel.Log().Info("registered event %s", iel.event) - iel.token = token - iel.SendAfter(iel.PID(), shutdown{}, inspectEventListIdlePeriod) - case shutdown: if iel.generating { iel.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/heap_inspector.go b/app/system/inspect/heap_inspector.go index cfcb8b31e..f9ecc2941 100644 --- a/app/system/inspect/heap_inspector.go +++ b/app/system/inspect/heap_inspector.go @@ -31,8 +31,19 @@ func (h *heap_inspector) Init(args ...any) error { h.name = args[1].(string) h.Log().SetLogger("default") - h.Send(h.PID(), register{}) h.SetCompression(true) + + eopts := gen.EventOptions{Notify: true, Buffer: 1} + hash := filterHash(h.name, "", "", "", 0, h.limit) + h.event = gen.Atom(fmt.Sprintf("%s_%s", inspectHeap, hash)) + token, err := h.RegisterEvent(h.event, eopts) + if err != nil { + h.Log().Error("unable to register event: %s", err) + return err + } + h.token = token + h.SendAfter(h.PID(), shutdown{}, inspectHeapIdlePeriod) + return nil } @@ -80,18 +91,6 @@ func (h *heap_inspector) HandleMessage(from gen.PID, message any) error { } h.SendResponse(m.pid, m.ref, response) - case register: - eopts := gen.EventOptions{Notify: true, Buffer: 1} - hash := filterHash(h.name, "", "", "", 0, h.limit) - h.event = gen.Atom(fmt.Sprintf("%s_%s", inspectHeap, hash)) - token, err := h.RegisterEvent(h.event, eopts) - if err != nil { - h.Log().Error("unable to register event: %s", err) - return err - } - h.token = token - h.SendAfter(h.PID(), shutdown{}, inspectHeapIdlePeriod) - case shutdown: if h.generating { break diff --git a/app/system/inspect/log.go b/app/system/inspect/log.go index 2395ba572..d77ca34b3 100644 --- a/app/system/inspect/log.go +++ b/app/system/inspect/log.go @@ -37,8 +37,21 @@ func (il *log) Init(args ...any) error { il.ring = make([]InspectLogEntry, il.limit) il.Log().SetLogger("default") il.Log().Debug("log inspector started (limit: %d)", il.limit) - il.Send(il.PID(), register{}) il.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + } + evname := gen.Atom(fmt.Sprintf("%s_%s", string(il.Name()), il.PID())) + token, err := il.RegisterEvent(evname, eopts) + if err != nil { + return err + } + + il.event = evname + il.token = token + il.SendAfter(il.PID(), shutdown{}, inspectLogIdlePeriod) + return nil } @@ -99,20 +112,6 @@ func (il *log) HandleMessage(from gen.PID, message any) error { } il.SendResponse(m.pid, m.ref, response) - case register: - eopts := gen.EventOptions{ - Notify: true, - } - evname := gen.Atom(fmt.Sprintf("%s_%s", string(il.Name()), il.PID())) - token, err := il.RegisterEvent(evname, eopts) - if err != nil { - return err - } - - il.event = evname - il.token = token - il.SendAfter(il.PID(), shutdown{}, inspectLogIdlePeriod) - case shutdown: if il.generating { break // ignore diff --git a/app/system/inspect/meta.go b/app/system/inspect/meta.go index 05916abd1..f9c1c378d 100644 --- a/app/system/inspect/meta.go +++ b/app/system/inspect/meta.go @@ -25,8 +25,22 @@ func (im *meta) Init(args ...any) error { im.meta = args[0].(gen.Alias) im.Log().SetLogger("default") im.Log().Debug("meta process inspector started. pid %s", im.meta) - // RegisterEvent is not allowed here - im.Send(im.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s", inspectMeta, im.meta)) + token, err := im.RegisterEvent(evname, eopts) + if err != nil { + im.Log().Error("unable to register meta process event: %s", err) + return err + } + im.Log().Info("registered event %s", evname) + im.event = evname + im.token = token + im.SendAfter(im.PID(), shutdown{}, inspectMetaIdlePeriod) + return nil } @@ -84,23 +98,6 @@ func (im *meta) HandleMessage(from gen.PID, message any) error { im.SendResponse(m.pid, m.ref, response) im.Log().Debug("sent response for the inspect meta request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s", inspectMeta, im.meta)) - token, err := im.RegisterEvent(evname, eopts) - if err != nil { - im.Log().Error("unable to register meta process event: %s", err) - return err - } - im.Log().Info("registered event %s", evname) - im.event = evname - - im.token = token - im.SendAfter(im.PID(), shutdown{}, inspectMetaIdlePeriod) - case shutdown: if im.generating { im.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/meta_state.go b/app/system/inspect/meta_state.go index 67f17df9b..31787de81 100644 --- a/app/system/inspect/meta_state.go +++ b/app/system/inspect/meta_state.go @@ -25,8 +25,22 @@ func (ims *meta_state) Init(args ...any) error { ims.meta = args[0].(gen.Alias) ims.Log().SetLogger("default") ims.Log().Debug("meta state inspector started. id %s", ims.meta) - // RegisterEvent is not allowed here - ims.Send(ims.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s", inspectMetaState, ims.meta)) + token, err := ims.RegisterEvent(evname, eopts) + if err != nil { + ims.Log().Error("unable to register meta state event: %s", err) + return err + } + ims.Log().Info("registered event %s", evname) + ims.event = evname + ims.token = token + ims.SendAfter(ims.PID(), shutdown{}, inspectMetaStateIdlePeriod) + return nil } @@ -75,23 +89,6 @@ func (ims *meta_state) HandleMessage(from gen.PID, message any) error { ims.SendResponse(m.pid, m.ref, response) ims.Log().Debug("sent response for the inspect meta state %s request to: %s", ims.meta, m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s", inspectMetaState, ims.meta)) - token, err := ims.RegisterEvent(evname, eopts) - if err != nil { - ims.Log().Error("unable to register meta state event: %s", err) - return err - } - ims.Log().Info("registered event %s", evname) - ims.event = evname - - ims.token = token - ims.SendAfter(ims.PID(), shutdown{}, inspectMetaStateIdlePeriod) - case shutdown: if ims.generating { ims.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/network.go b/app/system/inspect/network.go index 08839daf5..919766ef3 100644 --- a/app/system/inspect/network.go +++ b/app/system/inspect/network.go @@ -21,8 +21,20 @@ type network struct { func (in *network) Init(args ...any) error { in.Log().SetLogger("default") in.Log().Debug("network inspector started") - // RegisterEvent is not allowed here - in.Send(in.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + token, err := in.RegisterEvent(inspectNetwork, eopts) + if err != nil { + in.Log().Error("unable to register network event: %s", err) + return err + } + in.Log().Info("registered event %s", inspectNetwork) + in.token = token + in.SendAfter(in.PID(), shutdown{}, inspectNetworkIdlePeriod) + return nil } @@ -63,21 +75,6 @@ func (in *network) HandleMessage(from gen.PID, message any) error { in.SendResponse(m.pid, m.ref, response) in.Log().Debug("sent response for the inspect network request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - token, err := in.RegisterEvent(inspectNetwork, eopts) - if err != nil { - in.Log().Error("unable to register network event: %s", err) - return err - } - in.Log().Info("registered event %s", inspectNetwork) - - in.token = token - in.SendAfter(in.PID(), shutdown{}, inspectNetworkIdlePeriod) - case shutdown: if in.generating { in.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/node.go b/app/system/inspect/node.go index 90735875a..e30a12948 100644 --- a/app/system/inspect/node.go +++ b/app/system/inspect/node.go @@ -26,8 +26,20 @@ type node struct { func (in *node) Init(args ...any) error { in.Log().SetLogger("default") in.Log().Debug("node inspector started") - // RegisterEvent is not allowed here - in.Send(in.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + token, err := in.RegisterEvent(inspectNode, eopts) + if err != nil { + in.Log().Error("unable to register event: %s", err) + return err + } + in.Log().Info("registered event %s", inspectNode) + in.token = token + in.SendAfter(in.PID(), shutdown{}, inspectNodeIdlePeriod) + return nil } @@ -90,21 +102,6 @@ func (in *node) HandleMessage(from gen.PID, message any) error { in.SendResponse(m.pid, m.ref, response) in.Log().Debug("sent response for the inspect node request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - token, err := in.RegisterEvent(inspectNode, eopts) - if err != nil { - in.Log().Error("unable to register event: %s", err) - return err - } - in.Log().Info("registered event %s", inspectNode) - - in.token = token - in.SendAfter(in.PID(), shutdown{}, inspectNodeIdlePeriod) - case shutdown: if in.generating { in.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/process.go b/app/system/inspect/process.go index 86efa4f2c..c0fdb524b 100644 --- a/app/system/inspect/process.go +++ b/app/system/inspect/process.go @@ -25,8 +25,22 @@ func (ip *process) Init(args ...any) error { ip.pid = args[0].(gen.PID) ip.Log().SetLogger("default") ip.Log().Debug("process inspector started. pid %s", ip.pid) - // RegisterEvent is not allowed here - ip.Send(ip.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s", inspectProcess, ip.pid)) + token, err := ip.RegisterEvent(evname, eopts) + if err != nil { + ip.Log().Error("unable to register event: %s", err) + return err + } + ip.Log().Info("registered event %s", evname) + ip.event = evname + ip.token = token + ip.SendAfter(ip.PID(), shutdown{}, inspectProcessIdlePeriod) + return nil } @@ -90,23 +104,6 @@ func (ip *process) HandleMessage(from gen.PID, message any) error { ip.SendResponse(m.pid, m.ref, response) ip.Log().Debug("sent response for the inspect process request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s", inspectProcess, ip.pid)) - token, err := ip.RegisterEvent(evname, eopts) - if err != nil { - ip.Log().Error("unable to register event: %s", err) - return err - } - ip.Log().Info("registered event %s", evname) - ip.event = evname - - ip.token = token - ip.SendAfter(ip.PID(), shutdown{}, inspectProcessIdlePeriod) - case shutdown: if ip.generating { ip.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/process_list.go b/app/system/inspect/process_list.go index 2a8608734..3d6955ee0 100644 --- a/app/system/inspect/process_list.go +++ b/app/system/inspect/process_list.go @@ -41,8 +41,23 @@ func (ipl *process_list) Init(args ...any) error { ipl.Log().SetLogger("default") ipl.Log().Debug("process list inspector started. %d...%d", ipl.start, ipl.start+ipl.limit-1) - ipl.Send(ipl.PID(), register{}) ipl.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + evname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, ipl.start, ipl.start+ipl.limit-1)) + token, err := ipl.RegisterEvent(evname, eopts) + if err != nil { + ipl.Log().Error("unable to register event: %s", err) + return err + } + ipl.Log().Info("registered event %s", evname) + ipl.event = evname + ipl.token = token + ipl.SendAfter(ipl.PID(), shutdown{}, inspectProcessListIdlePeriod) + return nil } @@ -91,22 +106,6 @@ func (ipl *process_list) HandleMessage(from gen.PID, message any) error { ipl.SendResponse(m.pid, m.ref, response) ipl.Log().Debug("sent response for the inspect process list request to: %s", m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, - } - evname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, ipl.start, ipl.start+ipl.limit-1)) - token, err := ipl.RegisterEvent(evname, eopts) - if err != nil { - ipl.Log().Error("unable to register event: %s", err) - return err - } - ipl.Log().Info("registered event %s", evname) - ipl.event = evname - ipl.token = token - ipl.SendAfter(ipl.PID(), shutdown{}, inspectProcessListIdlePeriod) - case shutdown: if ipl.generating { ipl.Log().Debug("ignore shutdown. generating is active") diff --git a/app/system/inspect/process_range.go b/app/system/inspect/process_range.go index 7db7c1aa5..ab520b9dc 100644 --- a/app/system/inspect/process_range.go +++ b/app/system/inspect/process_range.go @@ -42,8 +42,22 @@ func (ipr *process_range) Init(args ...any) error { ipr.Log().SetLogger("default") ipr.Log().Debug("process range inspector started. name=%q behavior=%q app=%q state=%q mailbox>=%d limit=%d", ipr.name, ipr.behavior, ipr.application, ipr.state, ipr.minMailbox, ipr.limit) - ipr.Send(ipr.PID(), register{}) ipr.SetCompression(true) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, + } + ipr.event = gen.Atom(fmt.Sprintf("%s_%s", inspectProcessRange, ipr.hash)) + token, err := ipr.RegisterEvent(ipr.event, eopts) + if err != nil { + ipr.Log().Error("unable to register event: %s", err) + return err + } + ipr.Log().Info("registered event %s", ipr.event) + ipr.token = token + ipr.SendAfter(ipr.PID(), shutdown{}, inspectProcessRangeIdlePeriod) + return nil } @@ -121,21 +135,6 @@ func (ipr *process_range) HandleMessage(from gen.PID, message any) error { } ipr.SendResponse(m.pid, m.ref, response) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, - } - ipr.event = gen.Atom(fmt.Sprintf("%s_%s", inspectProcessRange, ipr.hash)) - token, err := ipr.RegisterEvent(ipr.event, eopts) - if err != nil { - ipr.Log().Error("unable to register event: %s", err) - return err - } - ipr.Log().Info("registered event %s", ipr.event) - ipr.token = token - ipr.SendAfter(ipr.PID(), shutdown{}, inspectProcessRangeIdlePeriod) - case shutdown: if ipr.generating { break diff --git a/app/system/inspect/process_state.go b/app/system/inspect/process_state.go index 8bdb1c40d..655ac511b 100644 --- a/app/system/inspect/process_state.go +++ b/app/system/inspect/process_state.go @@ -25,8 +25,22 @@ func (ips *process_state) Init(args ...any) error { ips.pid = args[0].(gen.PID) ips.Log().SetLogger("default") ips.Log().Debug("process state inspector started. pid %s", ips.pid) - // RegisterEvent is not allowed here - ips.Send(ips.PID(), register{}) + + eopts := gen.EventOptions{ + Notify: true, + Buffer: 1, // keep the last event + } + evname := gen.Atom(fmt.Sprintf("%s_%s", inspectProcessState, ips.pid)) + token, err := ips.RegisterEvent(evname, eopts) + if err != nil { + ips.Log().Error("unable to register process state event: %s", err) + return err + } + ips.Log().Info("registered event %s", evname) + ips.event = evname + ips.token = token + ips.SendAfter(ips.PID(), shutdown{}, inspectProcessStateIdlePeriod) + return nil } @@ -72,23 +86,6 @@ func (ips *process_state) HandleMessage(from gen.PID, message any) error { ips.SendResponse(m.pid, m.ref, response) ips.Log().Debug("sent response for the inspect process state %s request to: %s", ips.pid, m.pid) - case register: - eopts := gen.EventOptions{ - Notify: true, - Buffer: 1, // keep the last event - } - evname := gen.Atom(fmt.Sprintf("%s_%s", inspectProcessState, ips.pid)) - token, err := ips.RegisterEvent(evname, eopts) - if err != nil { - ips.Log().Error("unable to register process state event: %s", err) - return err - } - ips.Log().Info("registered event %s", evname) - ips.event = evname - - ips.token = token - ips.SendAfter(ips.PID(), shutdown{}, inspectProcessStateIdlePeriod) - case shutdown: if ips.generating { ips.Log().Debug("ignore shutdown. generating is active") From 2a611af396ab09ff591b469dd4ca2ac63f44eba4 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 12:03:03 +0100 Subject: [PATCH 056/122] add state time to process --- gen/process.go | 6 ++++++ node/node.go | 29 ++++++++++++++++++++--------- node/process.go | 5 ++++- node/process_run.go | 7 ++++++- node/process_run_pprof.go | 7 ++++++- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/gen/process.go b/gen/process.go index 52e3e17fb..1de48813c 100644 --- a/gen/process.go +++ b/gen/process.go @@ -931,6 +931,9 @@ type ProcessInfo struct { // State is the current process state (Init, Sleep, Running, WaitResponse, Terminated, Zombee). State ProcessState + // StateTime is the elapsed time since the process entered its current state (nanoseconds). + StateTime int64 + // Parent is the PID of the parent process that spawned this process. Parent PID @@ -1042,6 +1045,9 @@ type ProcessShortInfo struct { // State is the current process state (Init, Sleep, Running, WaitResponse, Terminated, Zombee). State ProcessState + // StateTime is the elapsed time since the process entered its current state (nanoseconds). + StateTime int64 + // Parent is the PID of the parent process that spawned this process. Parent PID diff --git a/node/node.go b/node/node.go index 71df49dd1..22cad2f2b 100644 --- a/node/node.go +++ b/node/node.go @@ -516,6 +516,7 @@ func (n *node) ProcessInfo(pid gen.PID) (gen.ProcessInfo, error) { info.MessagePriority = p.priority info.Uptime = p.Uptime() info.State = p.State() + info.StateTime = time.Now().UnixNano() - atomic.LoadInt64(&p.stateEntered) info.Parent = p.parent info.Leader = p.leader info.Fallback = p.fallback @@ -925,6 +926,7 @@ func (n *node) ProcessListShortInfo(start, limit int, filter ...func(gen.Process RunningTime: process.runningTime, Uptime: process.Uptime(), State: process.State(), + StateTime: time.Now().UnixNano() - atomic.LoadInt64(&process.stateEntered), Parent: process.parent, Leader: process.leader, LogLevel: process.log.Level(), @@ -966,6 +968,7 @@ func (n *node) ProcessRangeShortInfo(fn func(gen.ProcessShortInfo) bool) error { Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), + StateTime: time.Now().UnixNano() - atomic.LoadInt64(&p.stateEntered), Parent: p.parent, Leader: p.leader, LogLevel: p.log.Level(), @@ -1667,6 +1670,7 @@ func (n *node) Kill(pid gen.PID) error { case int32(gen.ProcessStateInit), int32(gen.ProcessStateWaitResponse), int32(gen.ProcessStateRunning): + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) // do not unregister process until its goroutine stopped return nil case int32(gen.ProcessStateTerminated): @@ -1678,6 +1682,7 @@ func (n *node) Kill(pid gen.PID) error { if old == int32(gen.ProcessStateTerminated) { return nil } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) // unregister process and stuff belonging to it n.unregisterProcess(p, gen.TerminateReasonKill) @@ -1919,6 +1924,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), + StateTime: time.Now().UnixNano() - atomic.LoadInt64(&p.stateEntered), Parent: p.parent, Leader: p.leader, LogLevel: p.log.Level(), @@ -1957,6 +1963,7 @@ func (n *node) ApplicationProcessListShortInfo(name gen.Atom, limit int) ([]gen. Wakeups: p.wakeups, Uptime: p.Uptime(), State: p.State(), + StateTime: time.Now().UnixNano() - atomic.LoadInt64(&p.stateEntered), Parent: p.parent, Leader: p.leader, LogLevel: p.log.Level(), @@ -2331,16 +2338,18 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra return empty, gen.ErrParentUnknown } + now := time.Now() p := &process{ - node: n, - response: make(chan response, 10), - creation: time.Now().Unix(), - keeporder: true, - state: int32(gen.ProcessStateInit), - parent: options.ParentPID, - leader: options.ParentLeader, - application: options.Application, - important: options.ImportantDelivery, + node: n, + response: make(chan response, 10), + creation: now.Unix(), + keeporder: true, + state: int32(gen.ProcessStateInit), + stateEntered: now.UnixNano(), + parent: options.ParentPID, + leader: options.ParentLeader, + application: options.Application, + important: options.ImportantDelivery, } if options.Register != "" { @@ -2477,6 +2486,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra // timeout won - main already called Kill, we do cleanup atomic.StoreInt32(&p.state, int32(gen.ProcessStateTerminated)) + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) n.cleanupProcess(p, gen.TerminateReasonKill) if lib.Recover() { defer func() { @@ -2539,6 +2549,7 @@ func (n *node) spawn(factory gen.ProcessFactory, options gen.ProcessOptionsExtra // switch to sleep state (process already registered above) p.state = int32(gen.ProcessStateSleep) + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) // do not count system app processes if p.application != system.Name { diff --git a/node/process.go b/node/process.go index 730819e4e..cbccaa32d 100644 --- a/node/process.go +++ b/node/process.go @@ -29,7 +29,8 @@ type process struct { behavior gen.ProcessBehavior sbehavior string - state int32 + state int32 + stateEntered int64 // Unix nanoseconds when current state was entered parent gen.PID leader gen.PID @@ -1952,6 +1953,7 @@ func (p *process) waitResponse(ref gen.Ref, timeout int) (any, error) { atomic.StoreInt32(&p.state, prevState) return nil, gen.ErrNotAllowed } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) timer := lib.TakeTimer() defer lib.ReleaseTimer(timer) @@ -1994,5 +1996,6 @@ retry: if swapped := atomic.CompareAndSwapInt32(&p.state, int32(gen.ProcessStateWaitResponse), prevState); swapped == false { return nil, gen.ErrProcessTerminated } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) return response, err } diff --git a/node/process_run.go b/node/process_run.go index dcd0e2826..dc2db0386 100644 --- a/node/process_run.go +++ b/node/process_run.go @@ -17,6 +17,7 @@ func (p *process) run() { int32(gen.ProcessStateRunning)) == false { // already running or terminated return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) atomic.AddUint64(&p.wakeups, 1) go func() { if lib.Recover() { @@ -29,6 +30,7 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, gen.TerminateReasonPanic) p.behavior.ProcessTerminate(gen.TerminateReasonPanic) } @@ -51,7 +53,7 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } - + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, e) p.behavior.ProcessTerminate(err) return @@ -71,10 +73,12 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, gen.TerminateReasonKill) p.behavior.ProcessTerminate(gen.TerminateReasonKill) return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) // check if something left in the inbox and try to handle it if p.mailbox.Main.Item() == nil { if p.mailbox.System.Item() == nil { @@ -95,6 +99,7 @@ func (p *process) run() { // another goroutine is already running return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) goto next }() } diff --git a/node/process_run_pprof.go b/node/process_run_pprof.go index b1f2bd78c..08caf4cff 100644 --- a/node/process_run_pprof.go +++ b/node/process_run_pprof.go @@ -19,6 +19,7 @@ func (p *process) run() { int32(gen.ProcessStateRunning)) == false { // already running or terminated return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) atomic.AddUint64(&p.wakeups, 1) go func() { labels := pprof.Labels("pid", p.pid.String()) @@ -33,6 +34,7 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, gen.TerminateReasonPanic) p.behavior.ProcessTerminate(gen.TerminateReasonPanic) } @@ -55,7 +57,7 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } - + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, e) p.behavior.ProcessTerminate(err) return @@ -75,10 +77,12 @@ func (p *process) run() { if old == int32(gen.ProcessStateTerminated) { return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) p.node.unregisterProcess(p, gen.TerminateReasonKill) p.behavior.ProcessTerminate(gen.TerminateReasonKill) return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) // check if something left in the inbox and try to handle it if p.mailbox.Main.Item() == nil { if p.mailbox.System.Item() == nil { @@ -99,6 +103,7 @@ func (p *process) run() { // another goroutine is already running return } + atomic.StoreInt64(&p.stateEntered, time.Now().UnixNano()) goto next }) }() From b4d42bcfe752ee578a785b49a14a1520ec107e39 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 16:11:22 +0100 Subject: [PATCH 057/122] update README.md --- README.md | 2 +- docs/.gitbook/assets/observer.png | Bin 0 -> 1058190 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/.gitbook/assets/observer.png diff --git a/README.md b/README.md index 6a91bd0cf..10dfc1158 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Available benchmarks can be found in the [benchmarks repository](https://github. ### Observer ### To inspect the node, network stack, running applications, and processes, you can use the [`observer`](https://github.com/ergo-services/tools/) tool - + To install the Observer tool, you need to have the Go compiler version 1.20 or higher. Run the following command: diff --git a/docs/.gitbook/assets/observer.png b/docs/.gitbook/assets/observer.png new file mode 100644 index 0000000000000000000000000000000000000000..c8d0b0dc343d1ecf8c17939e2cb2afc3f102f917 GIT binary patch literal 1058190 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�C`C117ga{&L~y8)}8nmLmAsw_0MD7hPA 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

6fOtflcMPt6!tSiqJmfapXq6@t} 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

-Wvwm`5Fn++`l;z}d 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Ξ3x1KGKiY! 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 Ry@36;Z_W6i>6iPC{wouTDf$2a literal 0 HcmV?d00001 From 0927a3831bb0b2eb36189caba10afcc95386b48c Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 16:12:24 +0100 Subject: [PATCH 058/122] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 10dfc1158..a5b286d06 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Available benchmarks can be found in the [benchmarks repository](https://github. ### Observer ### To inspect the node, network stack, running applications, and processes, you can use the [`observer`](https://github.com/ergo-services/tools/) tool - + To install the Observer tool, you need to have the Go compiler version 1.20 or higher. Run the following command: From c2bb5f0a2bb5dafffa59e76bb825a4ad9f1cff1d Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Thu, 19 Mar 2026 16:13:51 +0100 Subject: [PATCH 059/122] update README.md --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a5b286d06..a6bfc753c 100644 --- a/README.md +++ b/README.md @@ -43,17 +43,25 @@ Available benchmarks can be found in the [benchmarks repository](https://github. * Distributed Pub/Sub (event delivery to 1,000,000 subscribers across 10 nodes) ### Observer ### -To inspect the node, network stack, running applications, and processes, you can use the [`observer`](https://github.com/ergo-services/tools/) tool + +Observer is a real-time web UI for monitoring and inspecting Ergo nodes. It connects to a running node via SSE and provides live visibility into every layer of the system: + +- **Processes** — full process list with state, mailbox depth, latency, running time, wakeups, and uptime. Click any process to inspect its supervision tree, links, monitors, aliases, environment, and internal actor state +- **Applications** — running applications with their process trees, modes, and uptime +- **Network** — cluster topology, per-node connection details, traffic counters, and protocol info +- **Events** — registered events with producer, subscriber counts, and publication statistics +- **Logs** — live log stream with level filtering across the cluster +- **Profiler** — goroutine dump with grouping and stack traces, heap profile with allocation breakdown, and GC pressure charts -To install the Observer tool, you need to have the Go compiler version 1.20 or higher. Run the following command: +To install the Observer tool, you need to have the Go compiler version 1.20 or higher: ``` $ go install ergo.tools/observer@latest ``` -You can also embed the [Observer application](https://docs.ergo.services/extra-library/applications/observer) into your node. To see it in action, see the [demo example](https://github.com/ergo-services/examples/tree/master/demo). For more information, visit the [Observer documentation](https://docs.ergo.services/tools/observer). +You can also embed the [Observer application](https://docs.ergo.services/extra-library/applications/observer) directly into your node so it starts alongside your service. To see it in action with a fully loaded cluster, see the [observability example](https://github.com/ergo-services/examples/tree/master/observability). For more information, visit the [Observer documentation](https://docs.ergo.services/tools/observer). From 743dba9efb339c6badb28ad014a46e77a9c1bf58 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 23 Mar 2026 19:22:55 +0100 Subject: [PATCH 060/122] sync --- README.md | 84 ++-- app/system/inspect/inspect.go | 29 +- app/system/inspect/log.go | 26 +- app/system/inspect/message.go | 23 +- app/system/inspect/node.go | 7 +- app/system/inspect/process_list.go | 3 +- app/system/inspect/process_range.go | 2 +- docs/SUMMARY.md | 2 +- docs/advanced/debugging.md | 4 +- docs/{tools => advanced}/observer.md | 0 docs/basics/events.md | 2 +- docs/extra-library/actors/health.md | 34 +- docs/extra-library/actors/metrics.md | 26 +- docs/extra-library/applications/observer.md | 98 +++- docs/extra-library/applications/radar.md | 18 +- docs/networking/network-stack.md | 8 +- docs/networking/network-transparency.md | 16 +- docs/tools/ergo.md | 505 +++++++++++++++----- gen/node.go | 3 + net/proto/connection.go | 6 +- node/network.go | 2 +- node/node.go | 4 +- 22 files changed, 608 insertions(+), 294 deletions(-) rename docs/{tools => advanced}/observer.md (100%) diff --git a/README.md b/README.md index a6bfc753c..06ef15cae 100644 --- a/README.md +++ b/README.md @@ -44,24 +44,28 @@ Available benchmarks can be found in the [benchmarks repository](https://github. ### Observer ### -Observer is a real-time web UI for monitoring and inspecting Ergo nodes. It connects to a running node via SSE and provides live visibility into every layer of the system: +Observer is a real-time web UI for monitoring and inspecting Ergo nodes. It provides live visibility into every layer of the system: -- **Processes** — full process list with state, mailbox depth, latency, running time, wakeups, and uptime. Click any process to inspect its supervision tree, links, monitors, aliases, environment, and internal actor state -- **Applications** — running applications with their process trees, modes, and uptime -- **Network** — cluster topology, per-node connection details, traffic counters, and protocol info -- **Events** — registered events with producer, subscriber counts, and publication statistics -- **Logs** — live log stream with level filtering across the cluster -- **Profiler** — goroutine dump with grouping and stack traces, heap profile with allocation breakdown, and GC pressure charts +- **Processes** - full process list with state, mailbox depth, latency, running time, wakeups, and uptime. Click any process to inspect its supervision tree, links, monitors, aliases, environment, and internal actor state +- **Applications** - running applications with their process trees, modes, and uptime +- **Network** - cluster topology, per-node connection details, traffic counters, and protocol info +- **Events** - registered events with producer, subscriber counts, and publication statistics +- **Logs** - live log stream with level filtering across the cluster +- **Profiler** - goroutine dump with grouping and stack traces, heap profile with allocation breakdown, and GC pressure charts -To install the Observer tool, you need to have the Go compiler version 1.20 or higher: +Add Observer to your node as an application: -``` -$ go install ergo.tools/observer@latest +```go +import "ergo.services/application/observer" + +options.Applications = []gen.ApplicationBehavior{ + observer.CreateApp(observer.Options{}), +} ``` -You can also embed the [Observer application](https://docs.ergo.services/extra-library/applications/observer) directly into your node so it starts alongside your service. To see it in action with a fully loaded cluster, see the [observability example](https://github.com/ergo-services/examples/tree/master/observability). For more information, visit the [Observer documentation](https://docs.ergo.services/tools/observer). +To see it in action with a fully loaded cluster, see the [observability example](https://github.com/ergo-services/examples/tree/master/observability). For more information, visit the [Observer documentation](https://docs.ergo.services/extra-library/applications/observer). @@ -75,60 +79,26 @@ To install use the following command: $ go install ergo.tools/ergo@latest ``` -Now, you can create your project with just one command. Here is example: - -Supervision tree - -``` - mynode - ├─ myapp - │ │ - │ └─ mysup - │ │ - │ └─ myactor - ├─ myweb - └─ myactor2 -``` - -To generate project for this design use the following command: +Create a project and start adding components: ``` -$ ergo -init MyNode \ - -with-app MyApp \ - -with-sup MyApp:MySup \ - -with-actor MySup:MyActor \ - -with-web MyWeb \ - -with-actor MyActor2 \ - -with-observer -``` - -as a result you will get generated project: - -``` - mynode - ├── apps - │ └── myapp - │ ├── myactor.go - │ ├── myapp.go - │ └── mysup.go - ├── cmd - │ ├── myactor2.go - │ ├── mynode.go - │ ├── myweb.go - │ └── myweb_worker.go - ├── go.mod - ├── go.sum - └── README.md +$ ergo init MyNode github.com/myorg/mynode +$ cd mynode +$ ergo add supervisor MyNodeApp:MySup +$ ergo add actor MySup:MyActor +$ go run ./cmd ``` -to try it: +The generated project is ready to run immediately. Add more components as your +service grows: ``` -$ cd mynode -$ go run ./cmd +$ ergo add actor --pool MySup:MyPool +$ ergo add app BackgroundApp +$ ergo add message MessageConnect --field ID:gen.Alias --field Addr:string ``` -Since we included Observer application, open http://localhost:9911 to inspect your node and running processes. +For the full command reference, see the [ergo tool documentation](https://docs.ergo.services/tools/ergo). ### Erlang support ### diff --git a/app/system/inspect/inspect.go b/app/system/inspect/inspect.go index 42deb1c18..edbd1c82b 100644 --- a/app/system/inspect/inspect.go +++ b/app/system/inspect/inspect.go @@ -185,7 +185,8 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error if r.Limit < 1 { r.Limit = 1000 } - pname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, r.Start, r.Start+r.Limit-1)) + hash := filterHash(r.Name, r.Behavior, r.Application, r.State, r.MinMailbox, r.Limit) + pname := gen.Atom(fmt.Sprintf("%s_%d_%s", inspectProcessList, r.Start, hash)) _, err := i.SpawnRegister(pname, factory_process_list, opts, r.Start, r.Limit, r.Name, r.Behavior, r.Application, r.State, r.MinMailbox) if err != nil && err != gen.ErrTaken { @@ -302,28 +303,9 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error }, } - name := "diwep" levels := r.Levels if len(r.Levels) > 0 { - b := []byte{} - sort.Slice(r.Levels, func(i, j int) bool { - return r.Levels[i] < r.Levels[j] - }) - for i := range r.Levels { - switch r.Levels[i] { - case gen.LogLevelDebug: - b = append(b, 'd') - case gen.LogLevelInfo: - b = append(b, 'i') - case gen.LogLevelWarning: - b = append(b, 'w') - case gen.LogLevelError: - b = append(b, 'e') - case gen.LogLevelPanic: - b = append(b, 'p') - } - } - name = string(b) + sort.Slice(levels, func(i, j int) bool { return levels[i] < levels[j] }) } else { levels = inspectLogFilter } @@ -333,8 +315,9 @@ func (i *inspect) HandleCall(from gen.PID, ref gen.Ref, request any) (any, error limit = 500 } - pname := gen.Atom(fmt.Sprintf("%s_%s_%d", inspectLog, name, limit)) - _, err := i.SpawnRegister(pname, factory_log, opts, levels, limit) + hash := fmt.Sprintf("%x", hashStr(fmt.Sprintf("%v|%d|%s|%v", levels, limit, r.MessagePattern, r.MessageExclude))) + pname := gen.Atom(fmt.Sprintf("%s_%s", inspectLog, hash)) + _, err := i.SpawnRegister(pname, factory_log, opts, levels, limit, r.MessagePattern, r.MessageExclude) if err != nil && err != gen.ErrTaken { return err, nil } diff --git a/app/system/inspect/log.go b/app/system/inspect/log.go index d77ca34b3..a568daec3 100644 --- a/app/system/inspect/log.go +++ b/app/system/inspect/log.go @@ -2,6 +2,7 @@ package inspect import ( "fmt" + "strings" "time" "ergo.services/ergo/act" @@ -17,10 +18,12 @@ type log struct { token gen.Ref event gen.Atom - levels []gen.LogLevel - limit int - generating bool - loopID uint64 + levels []gen.LogLevel + limit int + messagePattern string // lower-cased for fast matching + messageExclude bool + generating bool + loopID uint64 // ring buffer ring []InspectLogEntry @@ -34,6 +37,10 @@ const logFlushInterval = time.Second func (il *log) Init(args ...any) error { il.levels = args[0].([]gen.LogLevel) il.limit = args[1].(int) + if len(args) > 3 { + il.messagePattern = strings.ToLower(args[2].(string)) + il.messageExclude = args[3].(bool) + } il.ring = make([]InspectLogEntry, il.limit) il.Log().SetLogger("default") il.Log().Debug("log inspector started (limit: %d)", il.limit) @@ -139,10 +146,19 @@ func (il *log) HandleMessage(from gen.PID, message any) error { } func (il *log) HandleLog(message gen.MessageLog) error { + msg := fmt.Sprintf(message.Format, message.Args...) + + if il.messagePattern != "" { + contains := strings.Contains(strings.ToLower(msg), il.messagePattern) + if il.messageExclude == contains { + return nil + } + } + entry := InspectLogEntry{ Timestamp: message.Time.UnixNano(), Level: message.Level, - Message: fmt.Sprintf(message.Format, message.Args...), + Message: msg, Fields: message.Fields, } diff --git a/app/system/inspect/message.go b/app/system/inspect/message.go index 6b57c888c..d61711032 100644 --- a/app/system/inspect/message.go +++ b/app/system/inspect/message.go @@ -4,14 +4,15 @@ import "ergo.services/ergo/gen" type RequestInspectNode struct{} type ResponseInspectNode struct { - CRC32 string - Event gen.Event - OS string - Arch string - Cores int - Timezone string - Version gen.Version - Creation int64 + CRC32 string + Event gen.Event + OS string + Arch string + Cores int + Timezone string + GoVersion string + Version gen.Version + Creation int64 } type MessageInspectNode struct { @@ -87,8 +88,10 @@ type MessageInspectProcessList struct { // node logs type RequestInspectLog struct { - Levels []gen.LogLevel - Limit int + Levels []gen.LogLevel + Limit int + MessagePattern string + MessageExclude bool } type ResponseInspectLog struct { Event gen.Event diff --git a/app/system/inspect/node.go b/app/system/inspect/node.go index e30a12948..a41698091 100644 --- a/app/system/inspect/node.go +++ b/app/system/inspect/node.go @@ -83,9 +83,10 @@ func (in *node) HandleMessage(from gen.PID, message any) error { Node: in.Node().Name(), }, - Arch: runtime.GOARCH, - OS: runtime.GOOS, - Cores: runtime.NumCPU(), + Arch: runtime.GOARCH, + OS: runtime.GOOS, + Cores: runtime.NumCPU(), + GoVersion: runtime.Version(), Timezone: func() string { now := time.Now() name, _ := now.Zone() diff --git a/app/system/inspect/process_list.go b/app/system/inspect/process_list.go index 3d6955ee0..e8c2d4c67 100644 --- a/app/system/inspect/process_list.go +++ b/app/system/inspect/process_list.go @@ -47,7 +47,8 @@ func (ipl *process_list) Init(args ...any) error { Notify: true, Buffer: 1, } - evname := gen.Atom(fmt.Sprintf("%s_%d_%d", inspectProcessList, ipl.start, ipl.start+ipl.limit-1)) + hash := filterHash(ipl.name, ipl.behavior, ipl.application, ipl.state, ipl.minMailbox, ipl.limit) + evname := gen.Atom(fmt.Sprintf("%s_%d_%s", inspectProcessList, ipl.start, hash)) token, err := ipl.RegisterEvent(evname, eopts) if err != nil { ipl.Log().Error("unable to register event: %s", err) diff --git a/app/system/inspect/process_range.go b/app/system/inspect/process_range.go index ab520b9dc..a8af60b75 100644 --- a/app/system/inspect/process_range.go +++ b/app/system/inspect/process_range.go @@ -113,7 +113,7 @@ func (ipr *process_range) HandleMessage(from gen.PID, message any) error { return int(a.PID.ID - b.PID.ID) }) - // reuse MessageInspectProcessList — same payload format + // reuse MessageInspectProcessList, same payload format ev := MessageInspectProcessList{ Node: ipr.Node().Name(), Processes: list, diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index d2abe37a7..823095ecc 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -56,6 +56,7 @@ * [Message Versioning](advanced/message-versioning.md) * [Building a Cluster](advanced/building-a-cluster.md) * [Debugging](advanced/debugging.md) +* [Inspecting With Observer](advanced/observer.md) ## extra library @@ -82,5 +83,4 @@ ## Tools * [Boilerplate Code Generation](tools/ergo.md) -* [Inspecting With Observer](tools/observer.md) * [Saturn - Central Registrar](tools/saturn.md) diff --git a/docs/advanced/debugging.md b/docs/advanced/debugging.md index d4b578167..9a6537413 100644 --- a/docs/advanced/debugging.md +++ b/docs/advanced/debugging.md @@ -88,11 +88,11 @@ This activates: - **`MailboxLatency` field** in `ProcessShortInfo` for per-process latency snapshots - **`Node.ProcessRangeShortInfo()`** for efficient iteration over all processes with their latency data -Without the tag, `Latency()` returns -1 (disabled) and there is zero runtime overhead -- no timestamps are recorded, no atomic operations are added to the message path. +Without the tag, `Latency()` returns -1 (disabled) and there is zero runtime overhead: no timestamps are recorded, no atomic operations are added to the message path. The overhead with the tag enabled is approximately 10-25% on micro-benchmarks (LOCAL 1-1 scenario with a single producer and consumer exchanging messages). In real applications with many processes, the overhead is lower because the cost is amortized across concurrent operations. -Latency measurement answers the question "how long has the oldest message been sitting in this process's mailbox?" A high value means the process is not keeping up with incoming messages -- it is either overloaded, stuck in a long-running callback, or blocked. This is particularly useful for: +Latency measurement answers the question "how long has the oldest message been sitting in this process's mailbox?" A high value means the process is not keeping up with incoming messages: it is either overloaded, stuck in a long-running callback, or blocked. This is particularly useful for: - Identifying backpressure in actor pipelines - Detecting stuck processes before they cause cascading failures diff --git a/docs/tools/observer.md b/docs/advanced/observer.md similarity index 100% rename from docs/tools/observer.md rename to docs/advanced/observer.md diff --git a/docs/basics/events.md b/docs/basics/events.md index dac47af93..000ea51cb 100644 --- a/docs/basics/events.md +++ b/docs/basics/events.md @@ -134,7 +134,7 @@ node.EventRangeInfo(func(info gen.EventInfo) bool { Node-level aggregate counters are also available in `gen.NodeInfo` via `node.Info()`: `EventsPublished` (local producer publishes), `EventsReceived` (events arriving from remote nodes), `EventsLocalSent`, and `EventsRemoteSent`. -The [Metrics actor](../extra-library/actors/metrics.md) automatically exports these counters as Prometheus metrics, along with per-event top-N breakdowns by subscribers, published, local deliveries, and remote sent. It also tracks event utilization state -- whether events are actively used, waiting on demand, or idle. +The [Metrics actor](../extra-library/actors/metrics.md) automatically exports these counters as Prometheus metrics, along with per-event top-N breakdowns by subscribers, published, local deliveries, and remote sent. It also tracks event utilization state: whether events are actively used, waiting on demand, or idle. ## Practical Patterns diff --git a/docs/extra-library/actors/health.md b/docs/extra-library/actors/health.md index 80085e828..d9fbaa254 100644 --- a/docs/extra-library/actors/health.md +++ b/docs/extra-library/actors/health.md @@ -8,11 +8,11 @@ Actors register named signals with the health actor, optionally sending periodic Kubernetes uses three types of probes to manage pod lifecycle: -**Liveness** -- Is the application alive? A failing liveness probe causes Kubernetes to restart the pod. Use this for detecting deadlocks, infinite loops, or corrupted state that prevents the application from functioning. +**Liveness:** Is the application alive? A failing liveness probe causes Kubernetes to restart the pod. Use this for detecting deadlocks, infinite loops, or corrupted state that prevents the application from functioning. -**Readiness** -- Can the application serve traffic? A failing readiness probe removes the pod from service endpoints. Use this for temporary conditions like database connection loss, cache warming, or downstream dependency outages where restarting would not help. +**Readiness:** Can the application serve traffic? A failing readiness probe removes the pod from service endpoints. Use this for temporary conditions like database connection loss, cache warming, or downstream dependency outages where restarting would not help. -**Startup** -- Has the application finished initializing? A failing startup probe prevents liveness and readiness checks from running. Use this for slow-starting applications that need time to load data, run migrations, or establish connections before health checks begin. +**Startup:** Has the application finished initializing? A failing startup probe prevents liveness and readiness checks from running. Use this for slow-starting applications that need time to load data, run migrations, or establish connections before health checks begin. In traditional applications, you implement these probes as HTTP handlers that check internal state. In actor systems, the "state" is distributed across many processes. A database connection actor, a cache warmer, and a message queue consumer each know their own status, but no single actor knows the overall health. @@ -22,13 +22,13 @@ The health actor solves this by accepting signal registrations from any actor in The health actor follows a registration and heartbeat pattern: -1. **Actors register signals** -- Each actor that contributes to health sends a `RegisterRequest` to the health actor (synchronous Call), specifying a signal name, which probes it affects, and an optional heartbeat timeout. The Call returns after the signal is registered, preventing race conditions with subsequent heartbeats. +1. **Actors register signals:** Each actor that contributes to health sends a `RegisterRequest` to the health actor (synchronous Call), specifying a signal name, which probes it affects, and an optional heartbeat timeout. The Call returns after the signal is registered, preventing race conditions with subsequent heartbeats. -2. **The health actor monitors registrants** -- When a signal is registered, the health actor monitors the registering process. If that process terminates, all its signals are automatically marked as down. +2. **The health actor monitors registrants:** When a signal is registered, the health actor monitors the registering process. If that process terminates, all its signals are automatically marked as down. -3. **Actors send heartbeats** -- For signals with a timeout, the registering actor periodically sends `MessageHeartbeat`. If the heartbeat interval exceeds the timeout, the health actor marks the signal as down. +3. **Actors send heartbeats:** For signals with a timeout, the registering actor periodically sends `MessageHeartbeat`. If the heartbeat interval exceeds the timeout, the health actor marks the signal as down. -4. **HTTP handlers read atomic state** -- The HTTP handlers read pre-built JSON responses from atomic values. The actor goroutine rebuilds these atomic values after every state change. No mutexes or channels are involved in serving HTTP requests. +4. **HTTP handlers read atomic state:** The HTTP handlers read pre-built JSON responses from atomic values. The actor goroutine rebuilds these atomic values after every state change. No mutexes or channels are involved in serving HTTP requests. ```mermaid sequenceDiagram @@ -76,9 +76,9 @@ type ActorBehavior interface { All callbacks have default (no-op) implementations. You only override what you need. -`HandleSignalDown` is called when a signal transitions from up to down -- due to heartbeat timeout, process termination, or explicit `MessageSignalDown`. Use this for alerting, logging, or triggering recovery actions. +`HandleSignalDown` is called when a signal transitions from up to down, due to heartbeat timeout, process termination, or explicit `MessageSignalDown`. Use this for alerting, logging, or triggering recovery actions. -`HandleSignalUp` is called when a signal transitions from down to up -- via heartbeat recovery or explicit `MessageSignalUp`. Use this to log recovery events or update external systems. +`HandleSignalUp` is called when a signal transitions from down to up, via heartbeat recovery or explicit `MessageSignalUp`. Use this to log recovery events or update external systems. ## Basic Usage @@ -114,7 +114,7 @@ Default configuration: - **Path**: `/health` - **CheckInterval**: `1 second` -With no signals registered, all three endpoints return 200 with `{"status":"healthy"}`. This means a freshly started health actor does not block deployment. Signals opt in to health checking -- only registered signals can cause a probe to fail. +With no signals registered, all three endpoints return 200 with `{"status":"healthy"}`. This means a freshly started health actor does not block deployment. Signals opt in to health checking; only registered signals can cause a probe to fail. ## Configuration @@ -135,7 +135,7 @@ options := health.Options{ **CheckInterval** controls how frequently the actor checks for expired heartbeats. The actor sends itself a timer message at this interval and iterates over all signals with a non-zero timeout, marking expired ones as down. Shorter intervals detect failures faster but increase message processing overhead. For most applications, 1-2 seconds provides a good balance. -**Mux** accepts an external `*http.ServeMux`. When provided, the health actor registers its handlers on this mux and skips starting its own HTTP server. This is useful when you want to serve health endpoints alongside other HTTP handlers on a single port -- for example, combining with the [Metrics](metrics.md) actor. +**Mux** accepts an external `*http.ServeMux`. When provided, the health actor registers its handlers on this mux and skips starting its own HTTP server. This is useful when you want to serve health endpoints alongside other HTTP handlers on a single port, for example, combining with the [Metrics](metrics.md) actor. ```go mux := http.NewServeMux() @@ -202,7 +202,7 @@ health.SignalDown(process, to, signal) `Register` and `Unregister` use synchronous Call to confirm the operation completed. This prevents race conditions where a heartbeat or status update arrives before the signal is registered. All other helpers use async Send. -The `to` parameter accepts anything that identifies a process -- a `gen.Atom` name, `gen.PID`, `gen.ProcessID`, or `gen.Alias`. +The `to` parameter accepts anything that identifies a process: a `gen.Atom` name, `gen.PID`, `gen.ProcessID`, or `gen.Alias`. ### Message Types @@ -258,7 +258,7 @@ func (w *DBWorker) Terminate(reason error) { Choose the heartbeat interval to be at least 2x shorter than the timeout. This provides one missed heartbeat as a safety margin before the signal is marked as down. -When the actor crashes, the health actor receives a `gen.MessageDownPID` (because it monitors the registrant) and marks all signals from that process as down. Heartbeat timeout is a secondary detection mechanism for situations where the process is alive but the resource it manages is not -- for example, a database connection pool actor that is running but has lost all connections. +When the actor crashes, the health actor receives a `gen.MessageDownPID` (because it monitors the registrant) and marks all signals from that process as down. Heartbeat timeout is a secondary detection mechanism for situations where the process is alive but the resource it manages is not, for example, a database connection pool actor that is running but has lost all connections. ## HTTP Endpoints @@ -270,9 +270,9 @@ When the actor crashes, the health actor receives a `gen.MessageDownPID` (becaus Each endpoint evaluates only signals registered for that specific probe. A signal registered for `ProbeLiveness` only does not affect `/health/ready` or `/health/startup`. -**200 OK** -- all signals for this probe are up, or no signals are registered. +**200 OK:** all signals for this probe are up, or no signals are registered. -**503 Service Unavailable** -- at least one signal for this probe is down. +**503 Service Unavailable:** at least one signal for this probe is down. ### Response Format @@ -312,7 +312,7 @@ Heartbeat timeout catches situations where the process is alive but the resource ### Manual Control -Actors can explicitly report status changes using `MessageSignalUp` and `MessageSignalDown`. Use this when you can detect failures immediately without waiting for a timeout -- for example, catching a database connection error in a callback and immediately marking the signal as down, then marking it up again when the connection is re-established. +Actors can explicitly report status changes using `MessageSignalUp` and `MessageSignalDown`. Use this when you can detect failures immediately without waiting for a timeout, for example, catching a database connection error in a callback and immediately marking the signal as down, then marking it up again when the connection is re-established. ## Extending with Custom Behavior @@ -343,7 +343,7 @@ func (h *MyHealth) HandleSignalUp(signal gen.Atom) error { } ``` -Override `HandleMessage` to handle application-specific messages alongside health management. The health actor dispatches its own types internally (`RegisterRequest`/`UnregisterRequest` via HandleCall, `MessageHeartbeat`/`MessageSignalUp`/`MessageSignalDown` via HandleMessage) -- only unrecognized messages are forwarded to your callbacks. +Override `HandleMessage` to handle application-specific messages alongside health management. The health actor dispatches its own types internally (`RegisterRequest`/`UnregisterRequest` via HandleCall, `MessageHeartbeat`/`MessageSignalUp`/`MessageSignalDown` via HandleMessage); only unrecognized messages are forwarded to your callbacks. ## Kubernetes Configuration diff --git a/docs/extra-library/actors/metrics.md b/docs/extra-library/actors/metrics.md index 59bf8ca2d..ece1b1c33 100644 --- a/docs/extra-library/actors/metrics.md +++ b/docs/extra-library/actors/metrics.md @@ -1,12 +1,12 @@ # Metrics -The metrics actor collects runtime statistics from an Ergo node and exposes them as a Prometheus HTTP endpoint. It runs as a regular process -- spawn it, and it starts serving `/metrics` with node, network, process, and event telemetry. +The metrics actor collects runtime statistics from an Ergo node and exposes them as a Prometheus HTTP endpoint. It runs as a regular process: spawn it, and it starts serving `/metrics` with node, network, process, and event telemetry. For application-specific metrics (request rates, business counters), you extend the actor with custom Prometheus collectors. ## Why Monitor Actors -Actor systems are dynamic. Processes spawn and terminate constantly, messages flow through mailboxes asynchronously, and load depends on message routing and supervision trees. Traditional monitoring (thread pools, request queues) does not capture this. The metrics actor tracks process lifecycle, mailbox pressure, message throughput, event fanout, network traffic, and delivery errors -- giving visibility into what the actor runtime is actually doing. +Actor systems are dynamic. Processes spawn and terminate constantly, messages flow through mailboxes asynchronously, and load depends on message routing and supervision trees. Traditional monitoring (thread pools, request queues) does not capture this. The metrics actor tracks process lifecycle, mailbox pressure, message throughput, event fanout, network traffic, and delivery errors, giving visibility into what the actor runtime is actually doing. ## ActorBehavior Interface @@ -30,9 +30,9 @@ Only `Init()` is required. All other callbacks have default implementations. Two patterns for custom metrics: -**Periodic collection** -- implement `CollectMetrics()` to query state at intervals. Use when metrics reflect current state from other actors or external sources. +**Periodic collection:** implement `CollectMetrics()` to query state at intervals. Use when metrics reflect current state from other actors or external sources. -**Event-driven updates** -- implement `HandleMessage()` or `HandleEvent()` to update metrics as events occur. Use when your application produces natural event streams. +**Event-driven updates:** implement `HandleMessage()` or `HandleEvent()` to update metrics as events occur. Use when your application produces natural event streams. ## Basic Usage @@ -132,11 +132,11 @@ Always active. Counts messages queued in each process's mailbox. Distribution ac Always active. Includes: -- **Utilization** -- ratio of callback running time to uptime. Distribution, max, and top-N. -- **Init time** -- ProcessInit duration. Max and top-N. -- **Throughput** -- messages in/out per process (top-N) and node-level aggregates. -- **Wakeups and drains** -- wakeup count and drain ratio (messages processed per wakeup). Drain ratio distinguishes between slow callbacks (drain ~1) and high-throughput batching (drain ~100) at the same utilization level. -- **Liveness** -- detects processes stuck in blocking calls. Computed as `RunningTime / (Uptime * MailboxLatency)`. A healthy process has RunningTime growing with activity (high score). A process blocked in a mutex, channel, or IO has RunningTime frozen while uptime and latency keep growing (score drops over time). Zombie processes are excluded (detected separately). Bottom-N surfaces the most stuck processes. Requires `-tags=latency`. +- **Utilization:** ratio of callback running time to uptime. Distribution, max, and top-N. +- **Init time:** ProcessInit duration. Max and top-N. +- **Throughput:** messages in/out per process (top-N) and node-level aggregates. +- **Wakeups and drains:** wakeup count and drain ratio (messages processed per wakeup). Drain ratio distinguishes between slow callbacks (drain ~1) and high-throughput batching (drain ~100) at the same utilization level. +- **Liveness:** detects processes stuck in blocking calls. Computed as `RunningTime / (Uptime * MailboxLatency)`. A healthy process has RunningTime growing with activity (high score). A process blocked in a mutex, channel, or IO has RunningTime frozen while uptime and latency keep growing (score drops over time). Zombie processes are excluded (detected separately). Bottom-N surfaces the most stuck processes. Requires `-tags=latency`. ### Event Metrics @@ -220,7 +220,7 @@ func (m *AppMetrics) HandleMessage(from gen.PID, message any) error { ### Custom Top-N Metrics -Top-N metrics track the N highest (or lowest) values observed during each collection cycle. Unlike gauges or counters, a top-N metric accumulates observations and periodically flushes only the top entries to Prometheus as a GaugeVec. This is useful when you want to identify the most active, slowest, or largest items out of many -- without creating a separate time series for each one. +Top-N metrics track the N highest (or lowest) values observed during each collection cycle. Unlike gauges or counters, a top-N metric accumulates observations and periodically flushes only the top entries to Prometheus as a GaugeVec. This is useful when you want to identify the most active, slowest, or largest items out of many, without creating a separate time series for each one. Each top-N metric is managed by a dedicated actor spawned under a SimpleOneForOne supervisor. Registration creates this actor; observations are sent to it asynchronously. On each flush interval the actor writes the current top-N entries to Prometheus and resets for the next cycle. @@ -235,12 +235,12 @@ metrics.TopNObserve(w, gen.Atom("radar_topn_slowest_queries"), 0.250, []string{" metrics.TopNObserve(w, gen.Atom("radar_topn_slowest_queries"), 1.100, []string{"JOIN ...", "orders"}) ``` -The `to` parameter in `RegisterTopN` is the name of the supervisor managing top-N actors. The `to` parameter in `TopNObserve` is the actor name -- by convention `"radar_topn_" + metricName`. +The `to` parameter in `RegisterTopN` is the name of the supervisor managing top-N actors. The `to` parameter in `TopNObserve` is the actor name, by convention `"radar_topn_" + metricName`. Ordering modes: -- `metrics.TopNMax` -- keeps the N largest values (e.g., slowest queries, busiest actors, highest memory usage) -- `metrics.TopNMin` -- keeps the N smallest values (e.g., lowest latency, least active processes) +- `metrics.TopNMax`: keeps the N largest values (e.g., slowest queries, busiest actors, highest memory usage) +- `metrics.TopNMin`: keeps the N smallest values (e.g., lowest latency, least active processes) When the process that registered a top-N metric terminates, the actor automatically cleans up and unregisters its GaugeVec from Prometheus. diff --git a/docs/extra-library/applications/observer.md b/docs/extra-library/applications/observer.md index 797e29b77..faabd780d 100644 --- a/docs/extra-library/applications/observer.md +++ b/docs/extra-library/applications/observer.md @@ -1,6 +1,14 @@ +--- +description: Real-time web UI for monitoring and inspecting Ergo nodes +--- + # Observer -The Application _Observer_ provides a convenient web interface to view node status, network activity, and running processes in the node built with Ergo Framework. Additionally, it allows you to inspect the internal state of processes or meta-processes. The application is can also be used as a standalone tool Observer. For more details, see the section [Inspecting With Observer](../../tools/observer.md). You can add the _Observer_ application to your node during startup by including it in the node's startup options: +Observer is a web application that embeds into your node and provides real-time visibility into the running system. It uses Server-Sent Events (SSE) for live push updates to the browser. + +For a detailed description of the UI and all available views, see [Inspecting With Observer](../../advanced/observer.md). + +## Adding Observer to a node

import (
 	"ergo.services/ergo"
@@ -9,21 +17,91 @@ The Application _Observer_ provides a convenient web interface to view node stat
 )
 
 func main() {
-	opt := gen.NodeOptions{
-		Applications: []gen.ApplicationBehavior {
+	options := gen.NodeOptions{
+		Applications: []gen.ApplicationBehavior{
 			observer.CreateApp(observer.Options{}),
-		}
+		},
 	}
-	node, err := ergo.StartNode("example@localhost", opt)
-	if err != nil {
+	node, err := ergo.StartNode("mynode@localhost", options)
+	if err != nil {
 		panic(err)
 	}
 	node.Wait()
 }
 
-The function `observer.CreateApp` takes `observer.Options` as an argument, allowing you to configure the _Observer_ application. You can set: +Open `http://localhost:9911` in your browser. + +## Options + +`observer.CreateApp` accepts `observer.Options`: + +* **Host**: interface to listen on. Default: `localhost`. +* **Port**: HTTP port. Default: `9911`. +* **PoolSize**: number of worker processes handling requests. Default: `10`. +* **LogLevel**: log level for Observer's own processes. Default: `gen.LogLevelInfo`. + +## What Observer shows + +### Node + +General node information: name, version, OS, architecture, CPU cores, timezone, uptime, memory usage, process count, goroutine count. Memory graph updates live over the last 60 seconds. Node-level log level can be changed directly from this view. + +### Processes + +Full process list with per-process metrics: state, mailbox depth, message latency, running time, wakeup count, uptime. Supports filtering by name pattern, behavior type, application, state, and minimum mailbox depth. + +Clicking a process opens its detail view: supervision tree position, links, monitors, registered names, aliases, environment variables, and the internal state returned by `HandleInspect`. + +Any actor that implements `HandleInspect` exposes its state as a live-updating key-value panel in the browser: + +```go +func (a *MyActor) HandleInspect(from gen.PID, item ...string) map[string]string { + return map[string]string{ + "connections": fmt.Sprintf("%d", a.connCount), + "last_error": a.lastError, + } +} +``` + +### Meta-processes + +Meta-processes (TCP servers, WebSocket handlers, SSE handlers, Port processes, and others) with their state, type, and parent process. + +### Applications + +All loaded applications with state (loaded, running, stopping), mode, uptime, and their process groups. Full application process tree on click. Applications can be started, stopped, and unloaded from this view. + +### Network + +Network stack details: mode, acceptors, protocol and handshake versions, registrar. Connections tab lists all active remote node connections with traffic counters. + +### Events + +All registered events: producer PID, subscriber count, buffered flag, and publication statistics. Filter by name, notification mode, buffered mode, and minimum subscriber count. + +### Logs + +Live log stream from the observed node. Filter by level (debug, info, warning, error, panic). + +### Profiler + +**Goroutines** - dump of all goroutines with stack traces, grouping, and filtering by state and minimum wait time. + +**Heap** - allocation profile showing top call sites by bytes. Filter by minimum allocation size. + +Both are available without restarting the node or enabling any special build flags. + +## Actions + +Observer is not read-only. From process and meta-process views you can: + +* **Send a message** to a process or meta-process +* **Send an exit signal** with a custom reason +* **Kill** a process +* **Change log level** for the node, a specific process, or a specific meta-process +* **Adjust per-process network settings**: send priority, message ordering (`KeepNetworkOrder`), important delivery, compression type/level/threshold + +## Inspecting the whole cluster -* **Port**: The port number for the web server (default: `9911` if not specified). -* **Host**: The interface name (default: `localhost`). -* **LogLevel**: The logging level for the Observer application (useful for debugging). The default is `gen.LogLevelInfo` +Observer communicates with the `system` application, which is started automatically on every Ergo node. Because of this, a single Observer instance can switch to any node in the cluster and inspect it without deploying anything extra to that node. Use the node selector in the UI to connect to any cluster node, via the registrar if configured, or by entering the host, port, and cookie explicitly. diff --git a/docs/extra-library/applications/radar.md b/docs/extra-library/applications/radar.md index d8eaf9b60..f0a8fe74c 100644 --- a/docs/extra-library/applications/radar.md +++ b/docs/extra-library/applications/radar.md @@ -2,7 +2,7 @@ Running an Ergo node in production typically requires two things: health probes for Kubernetes and a Prometheus metrics endpoint. Setting them up separately means two HTTP servers on two ports, two actor packages to import, and the same wiring code repeated on every node. -Radar bundles both into a single application on one HTTP port. Internally it runs a [Health](../actors/health.md) actor for probe endpoints, a [Metrics](../actors/metrics.md) actor for base Ergo telemetry, and a pool of metrics workers for custom metric updates -- all behind a shared mux served by one HTTP server. Actors interact with Radar through helper functions in the `radar` package without importing the underlying packages or knowing the internal actor names. +Radar bundles both into a single application on one HTTP port. Internally it runs a [Health](../actors/health.md) actor for probe endpoints, a [Metrics](../actors/metrics.md) actor for base Ergo telemetry, and a pool of metrics workers for custom metric updates, all behind a shared mux served by one HTTP server. Actors interact with Radar through helper functions in the `radar` package without importing the underlying packages or knowing the internal actor names. ## Adding to Your Node @@ -56,7 +56,7 @@ radar.Options{ **HealthCheckInterval** controls how often the health actor checks for expired heartbeats. Default is 1 second. Shorter intervals detect failures faster but increase internal message traffic. For most applications, 1-2 seconds provides a good balance. -**MetricsCollectInterval** sets how often base Ergo metrics are collected (processes, memory, CPU, network, events). Default is 10 seconds. Align this with your Prometheus scrape interval -- collecting more frequently than Prometheus scrapes wastes CPU; collecting less frequently means Prometheus may see stale values. +**MetricsCollectInterval** sets how often base Ergo metrics are collected (processes, memory, CPU, network, events). Default is 10 seconds. Align this with your Prometheus scrape interval; collecting more frequently than Prometheus scrapes wastes CPU; collecting less frequently means Prometheus may see stale values. **MetricsTopN** limits the number of entries in per-process and per-event top-N metrics tables. Default is 50. Increase this for large nodes with thousands of processes where you need broader visibility into the tail. The collection cost scales linearly with TopN. @@ -64,7 +64,7 @@ radar.Options{ ## Health Probes -Actors register signals with Radar, specifying which probes the signal affects and an optional heartbeat timeout. The health actor monitors the registering process -- if it terminates, all its signals are automatically marked as down. +Actors register signals with Radar, specifying which probes the signal affects and an optional heartbeat timeout. The health actor monitors the registering process; if it terminates, all its signals are automatically marked as down. ### Registering a Signal @@ -133,7 +133,7 @@ For a detailed explanation of the heartbeat model, failure detection mechanisms, Actors register Prometheus metric collectors and update them through Radar's helper functions. The underlying metrics actor manages the Prometheus registry and HTTP exposition. Registration is synchronous, updates are asynchronous. -All custom metrics automatically receive a `node` const label set to the node name. Do not include `"node"` in your variable label names -- it will cause a "duplicate label names" registration error. +All custom metrics automatically receive a `node` const label set to the node name. Do not include `"node"` in your variable label names; it will cause a "duplicate label names" registration error. ### Registering Metrics @@ -199,7 +199,7 @@ For a detailed explanation of metric types, the Grafana dashboard, and advanced ## Top-N Metrics -Top-N metrics track the N highest (or lowest) values observed during each collection cycle and flush them to Prometheus as a GaugeVec. This is useful when you want to identify outliers -- slowest queries, busiest workers, largest payloads -- without creating a time series per item. +Top-N metrics track the N highest (or lowest) values observed during each collection cycle and flush them to Prometheus as a GaugeVec. This is useful when you want to identify outliers (slowest queries, busiest workers, largest payloads) without creating a time series per item. ### Registering and Observing @@ -225,8 +225,8 @@ Registration is synchronous (returns error). Observations are asynchronous (fire ### Ordering Modes -- `radar.TopNMax` -- keeps the N largest values (e.g., slowest queries, busiest actors, highest memory) -- `radar.TopNMin` -- keeps the N smallest values (e.g., lowest latency, least active processes) +- `radar.TopNMax`: keeps the N largest values (e.g., slowest queries, busiest actors, highest memory) +- `radar.TopNMin`: keeps the N smallest values (e.g., lowest latency, least active processes) ### Automatic Cleanup @@ -359,10 +359,10 @@ scrape_configs: scrape_interval: 15s ``` -Align `scrape_interval` with `MetricsCollectInterval` in Radar options. The default collect interval is 10 seconds -- scraping more frequently than the collect interval returns identical data. +Align `scrape_interval` with `MetricsCollectInterval` in Radar options. The default collect interval is 10 seconds; scraping more frequently than the collect interval returns identical data. ## Relationship to Health and Metrics Actors -Radar uses [Health](../actors/health.md) and [Metrics](../actors/metrics.md) actors internally. The helper functions in the `radar` package delegate to these actors by their internal registered names. If you need capabilities beyond what the helpers expose -- embedding the metrics actor for direct Prometheus registry access, custom health actor behavior with `HandleSignalDown` callbacks, or shared mux with additional HTTP handlers -- use the underlying actors directly. +Radar uses [Health](../actors/health.md) and [Metrics](../actors/metrics.md) actors internally. The helper functions in the `radar` package delegate to these actors by their internal registered names. If you need capabilities beyond what the helpers expose (embedding the metrics actor for direct Prometheus registry access, custom health actor behavior with `HandleSignalDown` callbacks, or shared mux with additional HTTP handlers), use the underlying actors directly. Radar is designed for the common case: production nodes that need standard health probes and Prometheus metrics with minimal setup. For advanced scenarios, the building blocks are available as separate packages. diff --git a/docs/networking/network-stack.md b/docs/networking/network-stack.md index 9213a259d..afede3177 100644 --- a/docs/networking/network-stack.md +++ b/docs/networking/network-stack.md @@ -103,7 +103,7 @@ After handshake, the accepting node tells the dialing node to create a connectio The dialing node opens additional TCP connections using a shortened join handshake (skips full authentication since the first connection already authenticated). These connections join the pool, forming a single logical connection with multiple physical TCP links. -Multiple connections enable parallel message delivery. Each message goes to a connection based on the sender's identity, and the receiving side creates multiple receive queues per TCP connection for concurrent processing. This two-level mechanism -- sender-side link selection and receiver-side queue routing -- preserves per-sender message ordering while enabling parallelism across different senders. For details on how ordering works, including the `KeepNetworkOrder` flag and when to disable it, see [Message Ordering](network-transparency.md#message-ordering). +Multiple connections enable parallel message delivery. Each message goes to a connection based on the sender's identity, and the receiving side creates multiple receive queues per TCP connection for concurrent processing. This two-level mechanism (sender-side link selection and receiver-side queue routing) preserves per-sender message ordering while enabling parallelism across different senders. For details on how ordering works, including the `KeepNetworkOrder` flag and when to disable it, see [Message Ordering](network-transparency.md#message-ordering). ### Software Keepalive @@ -161,9 +161,9 @@ For details on protocol framing, order bytes, receive queue distribution, and th *Introduced in v3.3.0.* -When a message exceeds the fragment size threshold (default 65000 bytes), the framework splits it into smaller pieces for transmission and reassembles them on the receiving side. This happens after compression -- if a compressed message is still too large, it gets fragmented. From your code's perspective, nothing changes. You send a large message, and it arrives intact. +When a message exceeds the fragment size threshold (default 65000 bytes), the framework splits it into smaller pieces for transmission and reassembles them on the receiving side. This happens after compression; if a compressed message is still too large, it gets fragmented. From your code's perspective, nothing changes. You send a large message, and it arrives intact. -Fragmentation works with all message types: regular sends, important delivery, calls, and events. It composes with compression -- a message can be compressed first, then fragmented, and on the receiving side defragmented and then decompressed. +Fragmentation works with all message types: regular sends, important delivery, calls, and events. It composes with compression: a message can be compressed first, then fragmented, and on the receiving side defragmented and then decompressed. When [`KeepNetworkOrder`](network-transparency.md#message-ordering) is disabled for a process, the framework distributes fragments across all TCP connections in the pool, using the full bandwidth of the connection. This is useful for transferring large payloads where throughput matters more than ordering. When `KeepNetworkOrder` is enabled (the default), all fragments travel through a single TCP connection to preserve message ordering for that sender. @@ -184,7 +184,7 @@ node, err := ergo.StartNode("myapp@localhost", gen.NodeOptions{ }) ``` -`FragmentSize` controls at what point messages get split. This is a sender-side setting -- the receiver reassembles whatever arrives regardless of the sender's fragment size. Two nodes can use different fragment sizes. +`FragmentSize` controls at what point messages get split. This is a sender-side setting; the receiver reassembles whatever arrives regardless of the sender's fragment size. Two nodes can use different fragment sizes. `FragmentTimeout` sets how long the receiver waits for all fragments before discarding an incomplete assembly. If a sender crashes mid-message or a connection drops, partial assemblies are cleaned up after this timeout. diff --git a/docs/networking/network-transparency.md b/docs/networking/network-transparency.md index 173360a6e..f96e2f397 100644 --- a/docs/networking/network-transparency.md +++ b/docs/networking/network-transparency.md @@ -432,19 +432,19 @@ For detailed exploration of Important Delivery patterns, reliability guarantees, ## Message Ordering -Messages sent from process A to process B arrive in sending order. This is a per-sender FIFO guarantee -- it applies to each sender independently, not globally across all senders. The guarantee is enabled by default for every process. +Messages sent from process A to process B arrive in sending order. This is a per-sender FIFO guarantee; it applies to each sender independently, not globally across all senders. The guarantee is enabled by default for every process. ### KeepNetworkOrder Flag -Message ordering is controlled by a per-process flag called `KeepNetworkOrder`, which defaults to `true`. You can change it using `SetKeepNetworkOrder(bool)` during `Init` or at any point while the process is running. The flag applies to all outgoing messages from that process: `Send`, `Call`, `SendResponse`, and `SendEvent`. There is no per-message override -- ordering is all-or-nothing for a given sender. +Message ordering is controlled by a per-process flag called `KeepNetworkOrder`, which defaults to `true`. You can change it using `SetKeepNetworkOrder(bool)` during `Init` or at any point while the process is running. The flag applies to all outgoing messages from that process: `Send`, `Call`, `SendResponse`, and `SendEvent`. There is no per-message override; ordering is all-or-nothing for a given sender. -### How It Works -- Sender Side +### How It Works: Sender Side With ordering enabled, all messages from a process go through the same TCP link in the connection pool. The link is selected deterministically: `sender.ID % 255 % pool_size`. Since TCP guarantees FIFO delivery within a single connection, messages arrive at the remote node in exactly the order they were sent. With ordering disabled, messages are distributed round-robin across all pool links. This spreads the load for maximum throughput, but the arrival order across different TCP connections is no longer deterministic. -### How It Works -- Receiver Side +### How It Works: Receiver Side Each message carries an **order byte** in the protocol header (byte 6 of the ENP frame). When ordering is enabled, the order byte is derived from the recipient's identity: - For `gen.PID` recipients: `to.ID % 255` @@ -458,8 +458,8 @@ When ordering is disabled, the order byte is zero. Messages distribute round-rob The ordering mechanism works at two levels: -1. **Sender side** -- pins messages to one TCP link, preserving send order in the TCP stream -2. **Receiver side** -- pins messages to one decode queue, preserving decode order +1. **Sender side:** pins messages to one TCP link, preserving send order in the TCP stream +2. **Receiver side:** pins messages to one decode queue, preserving decode order Together they ensure end-to-end FIFO from sender to recipient. The sender side prevents reordering during transmission; the receiver side prevents reordering during decoding and dispatch. @@ -469,7 +469,7 @@ Some system messages have fixed ordering semantics regardless of the `KeepNetwor | Operation | Ordering | Notes | |-----------------|---------------|---------------------------------------------| -| `SendExit` | Always ordered| No `KeepNetworkOrder` check -- always uses sender-derived order byte | +| `SendExit` | Always ordered| No `KeepNetworkOrder` check, always uses sender-derived order byte | | `SendTerminate` | Always unordered | Order byte is always 0 | | Link/Monitor | Always ordered| System operations that must arrive in sequence | @@ -477,7 +477,7 @@ These are internal system messages where ordering behavior is fixed by the proto ### When to Disable Ordering -Processes that don't need ordering benefit from disabling it. When `KeepNetworkOrder` is `false`, messages spread across all TCP links in the pool and all receive queues on the remote side. This increases parallelism on both ends -- more connections are utilized for sending, and more goroutines participate in decoding. +Processes that don't need ordering benefit from disabling it. When `KeepNetworkOrder` is `false`, messages spread across all TCP links in the pool and all receive queues on the remote side. This increases parallelism on both ends: more connections are utilized for sending, and more goroutines participate in decoding. Good candidates for disabling ordering: - **Stateless workers** that process each request independently diff --git a/docs/tools/ergo.md b/docs/tools/ergo.md index 411c46ffb..81cddc45d 100644 --- a/docs/tools/ergo.md +++ b/docs/tools/ergo.md @@ -1,127 +1,384 @@ -# Boilerplate Code Generation - -The `ergo` tool allows you to generate the structure and source code for a project based on the Ergo Framework. To install it, use the following command: - -`go install ergo.tools/ergo@latest` - -Alternatively, you can build it from the source code available at [https://github.com/ergo-services/tools](https://github.com/ergo-services/tools). - -When using `ergo` tool, you need to follow the specific template for providing arguments: - -`Parent:Actor{param1:value1,param2:value2...}` - -* **Parent** can be a _supervisor_ (specified earlier with `-with-sup`) or an _application_ (specified earlier with `-with-app`). -* **Actor** can be an _actor_ (added earlier with `-with-actor`) or a _supervisor_ (specified earlier with `-with-sup`). - -This structured approach ensures the proper hierarchy and parameters are defined for your _actors_ and _supervisors_ - -### Available Arguments and Parameters : - -* **`-init `**: a required argument that sets the name of the node for your service. Available parameters: - * **`tls`**: enables encryption for network connections (a self-signed certificate will be used). - * **`module`**: allows you to specify the module name for the `go.mod` file. -* **`-path `**: specifies the path for the code of the generated project. -* **`-with-actor `**: adds an actor (based on `act.Actor`). -* **`-with-app `**: adds an application. Available parameters: - * **`mode`**: specifies the application's [start mode](../basics/application.md#application-startup-modes) (`temp` - Temporary, `perm` - Permanent, `trans` - Transient). The default mode is `trans`.\ - Example: `-with-app MyApp{mode:perm}` -* **`-with-sup `**: adds a supervisor (based on `act.Supervisor`). Available parameters: - * **`type`**: specifies the [type of supervisor](../actors/supervisor.md#supervisor-types) (`ofo` - One For One, `sofo` - Simple One For One, `afo` - All For One, `rfo` - Rest For One). The default type is `ofo`. - * **`strategy`**: specifies the [restart strategy](../actors/supervisor.md#restart-strategy) for the supervisor (`temp` - Temporary, `perm` - Permanent, `trans` - Transient). The default strategy is `trans`. -* **`-with-pool `**: adds a process pool actor (based on `act.Pool`). Available parameters: - * **`size`**: Specifies the number of worker processes in the pool. By default, 3 processes are started. -* **`-with-web `**: adds a Web server (based on `act.Pool` and `act.WebHandler`). Available parameters: - * **`host`**: specifies the hostname for the Web server. - * **`port`**: specifies the port number for the Web server. The default is `9090`. - * **`tls`**: enables encryption for the Web server using the node's `CertManager`. -* **`-with-tcp `**: adds a TCP server actor (based on `act.Actor` and `meta.TCPServer` meta-process). Available parameters: - * **`host`**: specifies the hostname for the TCP server. - * **`port`**: specifies the port number for the TCP server. The default is `7654`. - * **`tls`**: enables encryption for the TCP server using the node's `CertManager`. -* **`-with-udp `**: adds a UDP server actor (based on `act.Pool` , `meta.UDPServer` and `act.Actor` as worker processes). Available parameters: - * **`host`**: specifies the hostname for the UDP server. - * **`port`**: specifies the port number for the UDP server. The default is `7654`. -* **`-with-msg `**: adds a message type for network interactions. -* **`-with-logger `**: adds a logger from the extended library. Available loggers: [colored](../extra-library/loggers/colored.md), [rotate](../extra-library/loggers/rotate.md) -* **`-with-observer`**: adds the [Observer application](../extra-library/applications/observer.md). - -### Example - -For clarity, let's use all available arguments for `ergo` in the following example: - -
$ ergo -path /tmp/project \
-      -init demo{tls} \
-      -with-app MyApp \
-      -with-actor MyApp:MyActorInApp \
-      -with-sup MyApp:MySup \
-      -with-actor MySup:MyActorInSup \
-      -with-tcp "MySup:MyTCP{port:12345,tls}" \
-      -with-udp MySup:MyUDP{port:54321} \
-      -with-pool MySup:MyPool{size:4} \
-      -with-web "MyWeb{port:8888,tls}" \
-      -with-msg MyMsg1 \
-      -with-msg MyMsg2 \
-      -with-logger colored \
-      -with-logger rotate \
-      -with-observer
-      
-Generating project "/tmp/project/demo"...
-   generating "/tmp/project/demo/apps/myapp/myactorinapp.go"
-   generating "/tmp/project/demo/apps/myapp/myactorinsup.go"
-   generating "/tmp/project/demo/cmd/myweb.go"
-   generating "/tmp/project/demo/cmd/myweb_worker.go"
-   generating "/tmp/project/demo/apps/myapp/mytcp.go"
-   generating "/tmp/project/demo/apps/myapp/myudp.go"
-   generating "/tmp/project/demo/apps/myapp/myudp_worker.go"
-   generating "/tmp/project/demo/apps/myapp/mypool.go"
-   generating "/tmp/project/demo/apps/myapp/mypool_worker.go"
-   generating "/tmp/project/demo/apps/myapp/mysup.go"
-   generating "/tmp/project/demo/apps/myapp/myapp.go"
-   generating "/tmp/project/demo/types.go"
-   generating "/tmp/project/demo/cmd/demo.go"
-   generating "/tmp/project/demo/README.md"
-   generating "/tmp/project/demo/go.mod"
-   generating "/tmp/project/demo/go.sum"
-
-Successfully completed.
-
- -Pay attention to the values of the `-with-tcp` and `-with-web` arguments — they are enclosed in double quotes. If an argument has multiple parameters, they are separated by commas without spaces. However, since commas are argument delimiters for the shell interpreter, we enclose the entire value of the argument in double quotes to ensure the shell correctly processes the parameters. - -In our example, we specified two loggers: `colored` and `rotate`. This allows for colored log messages in the standard output as well as logging to files with log rotation functionality. In this case, the default logger is disabled to prevent duplicate log messages from appearing on the standard output. - -Additionally, we included the `observer` application. By default, this interface is accessible at `http://localhost:9911`. - -As a result of the generation process, we have a well-structured project source code that is ready for execution: - -``` - demo -├── apps -│ └── myapp -│ ├── myactorinapp.go -│ ├── myactorinsup.go -│ ├── myapp.go -│ ├── mypool.go -│ ├── mypool_worker.go -│ ├── mysup.go -│ ├── mytcp.go -│ ├── myudp.go -│ └── myudp_worker.go -├── cmd -│ ├── demo.go -│ ├── myweb.go -│ └── myweb_worker.go -├── go.mod -├── go.sum -├── README.md -└── types.go -``` - -The generated code is ready for compilation and execution: - -
- -Since this example includes the [observer application](../extra-library/applications/observer.md), you can open `http://localhost:9911` in your browser to access the web interface for [inspecting the node](observer.md) and its running processes. +--- +description: Boilerplate Generator for Ergo Framework Projects +--- +# ergo +The `ergo` tool generates the initial structure and source code for Ergo Framework +projects. Instead of writing actor definitions, supervisor specs, and application +boilerplate by hand, you describe what you want and the tool writes it for you. +The generated code is plain Go that you own and can modify freely. The tool +understands which parts are structural wiring (regenerated as the project grows) +and which parts are your business logic (never touched again). + +## Installation + +Requires Go 1.21 or higher. + +``` +go install ergo.tools/ergo@latest +``` + +## Quick Start + +Three commands to get a running Ergo node: + +```bash +ergo init MyNode github.com/myorg/mynode +cd mynode +go run ./cmd +``` + +The node starts immediately with an application, a supervisor and an actor, +all wired together. + +## How It Works + +The tool maintains `ergo.yaml` in the project root. This file describes the +supervision tree. Every `ergo add` command updates this file and regenerates +the affected code. + +Each component produces two files: + +| File | Owned by | Regenerated | Contains | +|------|----------|-------------|---------| +| `name_gen.go` | tool | on every `ergo add` or `ergo generate` | factory, Init spec, Load group | +| `name.go` | you | never | Tune, handlers, Start, Terminate | + +User-owned files provide hooks that the generated code calls. The pattern is +consistent across all component types: + +| File | Hook | Purpose | +|------|------|---------| +| `mysup.go` | `Tune(spec, args) (SupervisorSpec, error)` | adjust supervisor spec before start | +| `myapp.go` | `Tune(node, spec, args) (ApplicationSpec, error)` | adjust application spec before start | +| `messages.go` | `extraMessages() []any` | register custom EDF message types | +| `cmd/main.go` | `extraApps() []ApplicationBehavior` | add external applications | + +## Commands + +### ergo init + +``` +ergo init +``` + +Creates a new project. The directory name is derived from the last segment of +the module path. Generates `ergo.yaml`, all boilerplate, `go.mod`, and runs +`go mod tidy`. + +```bash +ergo init MyNode github.com/myorg/mynode +ergo init Gateway github.com/acme/api-gateway +``` + +The default project has one application, one supervisor and one actor, enough +to verify everything works before adding real components. + +### ergo add actor + +``` +ergo add actor [--pool] <[Parent:]Name> +``` + +Adds an actor. `Parent` is the name of an existing supervisor or application. +Without a parent the actor is added to `node.processes` and spawned directly +by the node at startup. + +`--pool` generates a pool actor with a companion worker type. A pool distributes +incoming messages across a fixed set of workers and restarts them on failure. + +```bash +ergo add actor MySup:MyActor +ergo add actor --pool MySup:RequestPool +ergo add actor StandaloneActor +``` + +### ergo add supervisor + +``` +ergo add supervisor [--type ] [--strategy ] <[Parent:]Name> +``` + +Adds a supervisor. `Parent` is an existing application or supervisor. + +`--type` controls which children are restarted when one fails: + +| Type | Behavior | +|------|---------| +| `one_for_one` (default) | only the failed child | +| `all_for_one` | all children | +| `rest_for_one` | the failed child and all children started after it | +| `simple_one_for_one` | children spawned dynamically at runtime via `AddChild`, no static children list | + +`--strategy` controls when a child is restarted: + +| Strategy | Behavior | +|----------|---------| +| `transient` (default) | only on abnormal exit | +| `permanent` | always | +| `temporary` | never | + +```bash +ergo add supervisor MyApp:WorkerSup +ergo add supervisor MyApp:CriticalSup --type all_for_one --strategy permanent +ergo add supervisor WorkerSup:SubSup --type rest_for_one +``` + +### ergo add app + +``` +ergo add app [--mode ] +``` + +Adds an application. `--mode` declares what happens when the application stops: + +| Mode | Behavior | +|------|---------| +| `transient` (default) | node stops on abnormal exit | +| `permanent` | node always stops when app exits | +| `temporary` | node ignores the exit | + +```bash +ergo add app MyApp +ergo add app BackgroundApp --mode temporary +ergo add app CriticalApp --mode permanent +``` + +### ergo add message + +``` +ergo add message --field name:type [--field name:type ...] +``` + +Adds an EDF message type. Field types can be standard Go types (`string`, `int`, +`bool`, `[]byte`) or framework types (`gen.Alias`, `gen.PID`, `gen.Ref`). + +Generated struct definitions and EDF registration go into `messages_gen.go`, +which is always regenerated when the message list changes. + +```bash +ergo add message MessageConnect --field ID:gen.Alias --field Addr:string +ergo add message MessageData --field ID:gen.Alias --field Payload:"[]byte" +``` + +If a message type has fields of other custom types, add the inner type first. +EDF requires nested types to be registered before the types that reference them: + +```bash +ergo add message MessageAddress --field City:string --field Street:string +ergo add message MessageUser --field Name:string --field Address:MessageAddress +``` + +Both nodes must register the same types with identical field definitions. The +registration order between nodes does not need to match; nodes negotiate numeric +type IDs during handshake. + +For detailed coverage of EDF, type constraints, and custom marshaling, see +[Network Transparency](../networking/network-transparency.md#edf-ergo-data-format). + +### ergo generate + +``` +ergo generate [ergo.yaml] +``` + +Regenerates all `*_gen.go` files from `ergo.yaml`. Your `.go` files are never +overwritten. Searches for `ergo.yaml` in the current directory and its parents. + +```bash +ergo generate +ergo generate /path/to/ergo.yaml +``` + +## Project Structure + +After `ergo init MyNode github.com/myorg/mynode`: + +``` +mynode/ + ergo.yaml project definition + go.mod + go.sum + messages_gen.go EDF struct definitions + registration (generated) + messages.go extraMessages() hook for custom types (yours) + apps/ + mynodeapp/ + mynodeapp_gen.go CreateApp, Load with Group (generated) + mynodeapp.go Tune, Start, Terminate (yours) + mynodesup_gen.go factory, Init with SupervisorSpec (generated) + mynodesup.go Tune, HandleMessage (yours) + mynodeactor_gen.go factory (generated) + mynodeactor.go Init, HandleMessage, HandleCall (yours) + cmd/ + main_gen.go node startup, application list (generated) + main.go extraApps() hook (yours) + README.md +``` + +The `README.md` is regenerated on every `ergo add` or `ergo generate` and shows +the current supervision tree. + +## ergo.yaml Reference + +```yaml +node: + name: MyNode + module: github.com/myorg/mynode + host: localhost + + network: + tls: false + cookie: "" # empty means auto-generated on every start + + loggers: # colored, rotate + - colored + + apps: + + # User-defined application + - name: MyApp + mode: transient + children: + - sup: MySup + type: one_for_one + strategy: transient + intensity: 2 # max restarts within period + period: 5 # seconds + children: + - actor: MyActor + - actor: MyPool + pool: true + + # Known applications from the ergo.services ecosystem + - observer + - mcp + - radar + + processes: # spawned directly by node, no application + - actor: StandaloneActor + + messages: + - name: MessageConnect + fields: + - ID: gen.Alias + - Addr: string +``` + +Known loggers: `colored` ([docs](../extra-library/loggers/colored.md)), +`rotate` ([docs](../extra-library/loggers/rotate.md)). + +Known applications: `observer` ([docs](../extra-library/applications/observer.md)), +`mcp` ([docs](../extra-library/applications/mcp.md)), +`radar` ([docs](../extra-library/applications/radar.md)). + +## Customizing Generated Code + +### Supervisor + +`mynodesup.go` contains `Tune`, called from the generated `Init`. The generated +`Init` builds `SupervisorSpec` from `ergo.yaml` and passes it to `Tune`. Override +restart parameters or add dynamic children here: + +```go +func (sup *MySup) Tune(spec act.SupervisorSpec, args ...any) (act.SupervisorSpec, error) { + spec.Restart.Intensity = 10 + spec.Restart.Period = 30 + return spec, nil +} +``` + +Do not replace `spec.Children` in `Tune` unless you have a specific reason. +The children list is populated from `ergo.yaml` by the generated `Init`. + +### Application + +`mynodeapp.go` contains `Tune`, called from the generated `Load`. The `Group` +in `Load` is populated from `ergo.yaml`. Use `Tune` to set metadata, environment +variables or dependencies: + +```go +func (app *MyApp) Tune(node gen.Node, spec gen.ApplicationSpec, args ...any) (gen.ApplicationSpec, error) { + spec.Description = "main application" + spec.Version = gen.Version{Release: "1.0.0"} + spec.Env = map[gen.Env]any{ + "DB_HOST": "localhost", + "DB_PORT": 5432, + } + spec.Depends.Applications = []gen.Atom{"config"} + return spec, nil +} +``` + +### Custom EDF Message Types + +`messages.go` contains `extraMessages()`, called from the generated `init()`. +Add custom types that are not declared in `ergo.yaml`: + +```go +func extraMessages() []any { + return []any{ + MyCustomMessage{}, + AnotherMessage{}, + } +} +``` + +For types with unexported fields or special encoding needs, implement +`edf.Marshaler`/`Unmarshaler` or `encoding.BinaryMarshaler`/`Unmarshaler` +in a separate file. See [Network Transparency](../networking/network-transparency.md#edf-ergo-data-format). + +### External Applications + +Some applications cannot be described in `ergo.yaml` because their constructor +requires runtime arguments. Add them in `cmd/main.go`, which is never regenerated: + +```go +func extraApps() []gen.ApplicationBehavior { + return []gen.ApplicationBehavior{ + thirdparty.New(thirdparty.Options{ + DSN: os.Getenv("DATABASE_URL"), + Port: 8080, + }), + } +} +``` + +## Typical Workflow + +```bash +# 1. Create the project +ergo init OrderService github.com/acme/orders +cd orders + +# 2. Verify it runs +go run ./cmd + +# 3. Add the supervision tree incrementally +ergo add supervisor MyOrderServiceApp:ApiSup +ergo add actor ApiSup:HttpHandler +ergo add actor --pool ApiSup:RequestPool +ergo add supervisor MyOrderServiceApp:WorkerSup --type all_for_one +ergo add actor WorkerSup:OrderProcessor +ergo add actor WorkerSup:PaymentActor + +# 4. Add network message types +ergo add message MessageOrderCreated --field OrderID:string --field Total:int +ergo add message MessageOrderPaid --field OrderID:string + +# 5. Implement logic in .go files +# 6. Run, observe, iterate +go run ./cmd +``` + +Each `ergo add` updates `ergo.yaml`, regenerates `*_gen.go` files, and leaves +your `.go` files untouched. + +## What's Next + +- [Observer](observer.md): web UI for inspecting running nodes and processes +- [Actors](../actors): actor types, supervision and messaging patterns +- [Applications](../basics/application.md): application lifecycle and modes +- [Pool](../actors/pool.md): distributing work across worker processes +- [Network Transparency](../networking/network-transparency.md): EDF serialization and distributed messaging diff --git a/gen/node.go b/gen/node.go index f3919b29f..932f524a6 100644 --- a/gen/node.go +++ b/gen/node.go @@ -768,6 +768,9 @@ type NodeInfo struct { // ProcessesRunning is the number of processes currently in Running state. ProcessesRunning int64 + // ProcessesWaitResponse is the number of processes blocked in a synchronous Call. + ProcessesWaitResponse int64 + // ProcessesZombee is the number of killed processes (Zombee state). ProcessesZombee int64 diff --git a/net/proto/connection.go b/net/proto/connection.go index a65e0b7b3..c3b5d4f13 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -1697,7 +1697,7 @@ func (c *connection) serve(conn net.Conn, tail []byte) { return } - // handle keepalive silently — don't count, don't queue + // handle keepalive silently, don't count, don't queue if buf.B[7] == protoMessageSoftwareKeepAlive { lib.ReleaseBuffer(buf) buf = buftail @@ -1757,7 +1757,7 @@ func (c *connection) handleRecvQueue(q lib.QueueMPSC, qIdx int) { for { v, ok := q.Pop() if ok == false { - // queue drained -- clean stale ordered assemblies (safe: we hold queue lock) + // queue drained, clean stale ordered assemblies (safe: we hold queue lock) if localFragments != nil && len(localFragments) > 0 { now := time.Now() for seqID, asm := range localFragments { @@ -3335,7 +3335,7 @@ func (c *connection) handleFragmentOrdered(buf *lib.Buffer, assemblies map[uint3 return nil } - // TCP order guarantee -- append + // TCP order guarantee, append asm.payloads = append(asm.payloads, append([]byte(nil), payload...)) asm.received++ asm.totalBytes += len(payload) diff --git a/node/network.go b/node/network.go index b444fc677..a426e0784 100644 --- a/node/network.go +++ b/node/network.go @@ -1425,7 +1425,7 @@ func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOpt return } - // Join handshake for a connection that no longer exists — peer's pool expansion + // Join handshake for a connection that no longer exists, peer's pool expansion // arrived after the connection was terminated. Nothing to join, close silently. if result.PeerCreation == 0 { c.Close() diff --git a/node/node.go b/node/node.go index 22cad2f2b..f117deabf 100644 --- a/node/node.go +++ b/node/node.go @@ -818,7 +818,7 @@ func (n *node) Info() (gen.NodeInfo, error) { case gen.ProcessStateRunning: info.ProcessesRunning++ case gen.ProcessStateWaitResponse: - info.ProcessesRunning++ + info.ProcessesWaitResponse++ case gen.ProcessStateZombee: info.ProcessesZombee++ } @@ -924,6 +924,8 @@ func (n *node) ProcessListShortInfo(start, limit int, filter ...func(gen.Process MessagesMailbox: uint64(messagesMailbox), MailboxLatency: process.mailbox.Latency(), RunningTime: process.runningTime, + InitTime: process.initTime, + Wakeups: process.wakeups, Uptime: process.Uptime(), State: process.State(), StateTime: time.Now().UnixNano() - atomic.LoadInt64(&process.stateEntered), From 9d5d1f13dd7b384723c5766cb93f67fdc08ede4c Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 23 Mar 2026 19:57:27 +0100 Subject: [PATCH 061/122] sync --- README.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 06ef15cae..3244c911a 100644 --- a/README.md +++ b/README.md @@ -10,19 +10,27 @@ The Ergo Framework is an implementation of ideas, technologies, and design patte ### Features ### -1. **Actor Model**: isolated processes communicate through message passing, handling messages sequentially in their own mailbox with four priority queues. Processes support both asynchronous messaging and synchronous request-response patterns, enabling flexible communication while maintaining the actor model guarantees. +1. **Actor Model:** isolated processes communicate through message passing, handling messages sequentially with four priority queues. Supports asynchronous messaging and synchronous request-response, with per-process [mailbox latency measurement](https://docs.ergo.services/advanced/debugging#mailbox-latency) (`-tags=latency`) for production diagnostics. -2. **Network Transparency**: actors interact the same way whether local or remote. The framework uses custom serialization and protocol for [efficient](https://github.com/ergo-services/benchmarks) distributed communication with connection pooling, compression, and type caching, making network location transparent to application code. +2. **Network Transparency:** actors interact the same way whether local or remote. Uses EDF (Ergo Data Format), a custom binary serialization with type caching, pointer support, and [message versioning](https://docs.ergo.services/advanced/message-versioning) for seamless upgrades. Includes connection pooling, compression, [message fragmentation](https://docs.ergo.services/networking/network-stack#message-fragmentation), and [application-level keepalive](https://docs.ergo.services/networking/network-stack#software-keepalive) for silent failure detection. -3. **Supervision Trees**: hierarchical fault recovery where supervisors monitor child processes and apply restart strategies when failures occur. Supports multiple supervision types (One For One, All For One, Rest For One, Simple One For One) and restart strategies (Transient, Temporary, Permanent) for building self-healing systems. +3. **Supervision Trees:** hierarchical fault recovery where supervisors monitor child processes and apply configurable restart strategies. Supports One For One, All For One, Rest For One, and Simple One For One supervision types with Transient, Temporary, and Permanent restart policies. -4. **Meta Processes**: bridge blocking I/O with the actor model through dedicated meta processes that handle TCP, UDP, Port, and Web protocols. Meta processes run blocking operations without affecting regular actor message processing. +4. **Meta Processes:** bridge blocking I/O with the actor model through dedicated meta processes handling [TCP](https://docs.ergo.services/meta-processes/tcp), [UDP](https://docs.ergo.services/meta-processes/udp), [Port](https://docs.ergo.services/meta-processes/port), [Web](https://docs.ergo.services/meta-processes/web), [WebSocket](https://docs.ergo.services/extra-library/meta-processes/websocket), and [SSE](https://docs.ergo.services/extra-library/meta-processes/sse) protocols without affecting regular actor message processing. -5. **Distributed Systems**: service discovery through embedded or external registrars (etcd, Saturn), distributed publish/subscribe events with token-based authorization and buffering, remote process spawning with factory-based permissions, and remote application orchestration across nodes. +5. **Distributed Systems:** service discovery via embedded or external registrars ([etcd](https://docs.ergo.services/extra-library/registrars/etcd-client), [Saturn](https://docs.ergo.services/extra-library/registrars/saturn-client)), distributed [publish/subscribe events](https://docs.ergo.services/basics/events) with token-based authorization and buffering, [remote process spawning](https://docs.ergo.services/networking/remote-spawn-process) with factory-based permissions, and [remote application orchestration](https://docs.ergo.services/networking/remote-start-application) across nodes. -6. **Ready-to-use Components**: core framework includes Actor, Supervisor, Pool, and WebWorker actors plus TCP, UDP, Port, and Web meta processes. Extra library provides Leader, Metrics actors, WebSocket, SSE meta processes, Observer application, Colored and Rotate loggers, Erlang protocol support. +6. **Observability:** real-time cluster inspection via the [Observer](https://docs.ergo.services/extra-library/applications/observer) web UI (processes, applications, network, events, logs, profiler) and production metrics via [Radar](https://docs.ergo.services/extra-library/applications/radar) with a ready-to-use Grafana dashboard covering process lifecycle, mailbox pressure, network traffic, and event fanout. -7. **Flexibility**: customize network stack components, certificate management, compression and message priorities, logging, distributed events, and meta processes. Framework supports mTLS, NAT traversal, important delivery for guaranteed messaging, and Cron-based scheduling. +7. **AI-Native:** built-in [MCP server](https://docs.ergo.services/extra-library/applications/mcp) exposes the full cluster to AI agents (Claude, Cursor, and any MCP-compatible client). Inspect processes, query events, capture goroutine dumps, stream logs, and run real-time samplers through natural language, turning any AI assistant into an interactive SRE for your Ergo cluster. + +8. **Cloud Native:** built-in Kubernetes health probes (liveness, readiness, startup) via the [Health](https://docs.ergo.services/extra-library/actors/health) actor, [Prometheus](https://docs.ergo.services/extra-library/actors/metrics) metrics endpoint, and [mTLS](https://docs.ergo.services/networking/mutual-tls) support for zero-trust deployments. + +9. **Ready-to-use Components:** core framework includes Actor, Supervisor, Pool, and WebWorker actors plus TCP, UDP, Port, WebSocket, SSE, and Web meta processes. Extra library provides [Leader](https://docs.ergo.services/extra-library/actors/leader), [Metrics](https://docs.ergo.services/extra-library/actors/metrics), and [Health](https://docs.ergo.services/extra-library/actors/health) actors, [Observer](https://docs.ergo.services/extra-library/applications/observer) and [Radar](https://docs.ergo.services/extra-library/applications/radar) applications, [Colored](https://docs.ergo.services/extra-library/loggers/colored) and [Rotate](https://docs.ergo.services/extra-library/loggers/rotate) loggers. + +10. **Erlang Interoperability:** native support for the [Erlang distribution protocol](https://docs.ergo.services/extra-library/network-protocols/erlang) enables heterogeneous clusters where Ergo (Go) and Erlang/Elixir nodes participate as equal peers. Send messages, spawn processes, and share events across language boundaries without any proxies or bridges. + +11. **Flexibility:** customize network stack, certificate management ([mTLS](https://docs.ergo.services/networking/mutual-tls), [NAT traversal](https://docs.ergo.services/networking/behind-the-nat)), compression and message priorities, [Cron-based scheduling](https://docs.ergo.services/basics/cron), [important delivery](https://docs.ergo.services/advanced/important-delivery) for guaranteed messaging, and logging. The [`ergo`](https://docs.ergo.services/tools/ergo) CLI tool generates project scaffolding, actors, supervisors, and message types from the command line. Examples demonstrating the framework's capabilities are available in the [examples repository](https://github.com/ergo-services/examples). @@ -71,7 +79,7 @@ To see it in action with a fully loaded cluster, see the [observability example] ### Quick start ### -For a quick start, use the [`ergo`](https://docs.ergo.services/tools/ergo) tool — a command-line utility designed to simplify the process of generating boilerplate code for your project based on the Ergo Framework. With this tool, you can rapidly create a complete project structure, including applications, actors, supervisors, network components, and more. It offers a set of arguments that allow you to customize the project according to specific requirements, ensuring it is ready for immediate development. +For a quick start, use the [`ergo`](https://docs.ergo.services/tools/ergo) tool, a command-line utility designed to simplify the process of generating boilerplate code for your project based on the Ergo Framework. With this tool, you can rapidly create a complete project structure, including applications, actors, supervisors, network components, and more. It offers a set of arguments that allow you to customize the project according to specific requirements, ensuring it is ready for immediate development. To install use the following command: From c9b971aa9effdf784bcc28f30da01a8a208099f9 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 23 Mar 2026 20:04:59 +0100 Subject: [PATCH 062/122] sync --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3244c911a..1946c7353 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ The Ergo Framework is an implementation of ideas, technologies, and design patte 4. **Meta Processes:** bridge blocking I/O with the actor model through dedicated meta processes handling [TCP](https://docs.ergo.services/meta-processes/tcp), [UDP](https://docs.ergo.services/meta-processes/udp), [Port](https://docs.ergo.services/meta-processes/port), [Web](https://docs.ergo.services/meta-processes/web), [WebSocket](https://docs.ergo.services/extra-library/meta-processes/websocket), and [SSE](https://docs.ergo.services/extra-library/meta-processes/sse) protocols without affecting regular actor message processing. -5. **Distributed Systems:** service discovery via embedded or external registrars ([etcd](https://docs.ergo.services/extra-library/registrars/etcd-client), [Saturn](https://docs.ergo.services/extra-library/registrars/saturn-client)), distributed [publish/subscribe events](https://docs.ergo.services/basics/events) with token-based authorization and buffering, [remote process spawning](https://docs.ergo.services/networking/remote-spawn-process) with factory-based permissions, and [remote application orchestration](https://docs.ergo.services/networking/remote-start-application) across nodes. +5. **Distributed Systems:** service discovery via embedded or external registrars ([etcd](https://docs.ergo.services/extra-library/registrars/etcd-client), [Saturn](https://docs.ergo.services/extra-library/registrars/saturn-client)), distributed [publish/subscribe events](https://docs.ergo.services/basics/events) with token-based authorization and buffering, [remote process spawning](https://docs.ergo.services/networking/remote-spawn-process) with factory-based permissions, [remote application orchestration](https://docs.ergo.services/networking/remote-start-application) across nodes, and Raft-based [leader election](https://docs.ergo.services/extra-library/actors/leader) without external dependencies for coordinating exclusive work across cluster replicas. -6. **Observability:** real-time cluster inspection via the [Observer](https://docs.ergo.services/extra-library/applications/observer) web UI (processes, applications, network, events, logs, profiler) and production metrics via [Radar](https://docs.ergo.services/extra-library/applications/radar) with a ready-to-use Grafana dashboard covering process lifecycle, mailbox pressure, network traffic, and event fanout. +6. **Observability:** real-time cluster inspection via the [Observer](https://docs.ergo.services/extra-library/applications/observer) web UI (processes, applications, network, events, logs, profiler) and production metrics via [Radar](https://docs.ergo.services/extra-library/applications/radar) with a ready-to-use Grafana dashboard covering process lifecycle, mailbox pressure, network traffic, and event fanout. The extensible [Metrics](https://docs.ergo.services/extra-library/actors/metrics) actor adds custom Prometheus collectors alongside built-in node telemetry, with periodic collection and event-driven update patterns for application-specific instrumentation. 7. **AI-Native:** built-in [MCP server](https://docs.ergo.services/extra-library/applications/mcp) exposes the full cluster to AI agents (Claude, Cursor, and any MCP-compatible client). Inspect processes, query events, capture goroutine dumps, stream logs, and run real-time samplers through natural language, turning any AI assistant into an interactive SRE for your Ergo cluster. From 0be2846405c2e255a337fa5c700f8f84ee49fa1f Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Mon, 23 Mar 2026 20:57:02 +0100 Subject: [PATCH 063/122] sync --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1946c7353..400745c01 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ The Ergo Framework is an implementation of ideas, technologies, and design patte 9. **Ready-to-use Components:** core framework includes Actor, Supervisor, Pool, and WebWorker actors plus TCP, UDP, Port, WebSocket, SSE, and Web meta processes. Extra library provides [Leader](https://docs.ergo.services/extra-library/actors/leader), [Metrics](https://docs.ergo.services/extra-library/actors/metrics), and [Health](https://docs.ergo.services/extra-library/actors/health) actors, [Observer](https://docs.ergo.services/extra-library/applications/observer) and [Radar](https://docs.ergo.services/extra-library/applications/radar) applications, [Colored](https://docs.ergo.services/extra-library/loggers/colored) and [Rotate](https://docs.ergo.services/extra-library/loggers/rotate) loggers. -10. **Erlang Interoperability:** native support for the [Erlang distribution protocol](https://docs.ergo.services/extra-library/network-protocols/erlang) enables heterogeneous clusters where Ergo (Go) and Erlang/Elixir nodes participate as equal peers. Send messages, spawn processes, and share events across language boundaries without any proxies or bridges. +10. **Erlang Interoperability:** native support for the [Erlang distribution protocol](https://docs.ergo.services/extra-library/network-protocols/erlang) enables heterogeneous clusters where Ergo (Go) and Erlang/Elixir nodes participate as equal peers. Send messages, spawn processes, and set up links and monitors across language boundaries without any proxies or bridges. 11. **Flexibility:** customize network stack, certificate management ([mTLS](https://docs.ergo.services/networking/mutual-tls), [NAT traversal](https://docs.ergo.services/networking/behind-the-nat)), compression and message priorities, [Cron-based scheduling](https://docs.ergo.services/basics/cron), [important delivery](https://docs.ergo.services/advanced/important-delivery) for guaranteed messaging, and logging. The [`ergo`](https://docs.ergo.services/tools/ergo) CLI tool generates project scaffolding, actors, supervisors, and message types from the command line. From aae97280a60a3c587c680e213906116e3c929960 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Mar 2026 17:08:35 +0100 Subject: [PATCH 064/122] tracing prep: add clockskew measurment --- gen/default.go | 9 +- gen/network.go | 11 ++ lib/flusher.go | 34 ++-- net/proto/connection.go | 169 ++++++++++++++++-- net/proto/enp.go | 7 +- net/proto/types.go | 4 +- node/network.go | 65 +++++-- .../t011_fragmentation_load_test.go | 20 ++- 8 files changed, 258 insertions(+), 61 deletions(-) diff --git a/gen/default.go b/gen/default.go index a916db56d..c26dade9e 100644 --- a/gen/default.go +++ b/gen/default.go @@ -27,9 +27,9 @@ var ( DefaultHandshakeTimeout time.Duration = 5 * time.Second DefaultSoftwareKeepAliveMisses int = 3 - DefaultFragmentSize int = 65000 - DefaultFragmentTimeout time.Duration = 30 * time.Second - DefaultMaxFragmentAssemblies int = 1000 + DefaultFragmentSize int = 65000 + DefaultFragmentTimeout time.Duration = 30 * time.Second + DefaultMaxFragmentAssemblies int = 1000 DefaultNetworkFlags = NetworkFlags{ Enable: true, @@ -40,7 +40,8 @@ var ( EnableProxyAccept: true, EnableImportantDelivery: true, EnableSimultaneousConnect: true, - EnableSoftwareKeepAlive: 15, // seconds + EnableClockSkew: true, + EnableSoftwareKeepAlive: 15, // seconds } DefaultNetworkProxyFlags = NetworkProxyFlags{ diff --git a/gen/network.go b/gen/network.go index 6feb80066..1194da7d7 100644 --- a/gen/network.go +++ b/gen/network.go @@ -409,6 +409,9 @@ type NetworkFlags struct { EnableImportantDelivery bool // EnableSimultaneousConnect enables simultaneous connect detection and resolution EnableSimultaneousConnect bool + // EnableClockSkew enables clock skew measurement between connected nodes. + // Both nodes must have it enabled for measurements to work. + EnableClockSkew bool // EnableSoftwareKeepAlive enables application-level keepalive with the given period in seconds. // Zero disables keepalive. Max 255. EnableSoftwareKeepAlive int @@ -453,6 +456,9 @@ func (nf NetworkFlags) MarshalEDF(w io.Writer) error { } flags |= uint64(period) << 8 } + if nf.EnableClockSkew == true { + flags |= 1 << 16 + } binary.BigEndian.PutUint64(buf[:], flags) w.Write(buf[:]) return nil @@ -475,6 +481,7 @@ func (nf *NetworkFlags) UnmarshalEDF(buf []byte) error { nf.EnableImportantDelivery = (flags & 64) > 0 nf.EnableSimultaneousConnect = (flags & 128) > 0 nf.EnableSoftwareKeepAlive = int((flags >> 8) & 0xFF) + nf.EnableClockSkew = (flags & (1 << 16)) > 0 return nil } @@ -589,6 +596,10 @@ type RemoteNodeInfo struct { DecompressedBytesRecv uint64 // DecompressedOrigRecv is the total bytes after decompression (original size). DecompressedOrigRecv uint64 + + // ClockSkew is the estimated clock offset relative to the remote node (nanoseconds). + // Positive value means remote clock is ahead. Zero if not yet measured. + ClockSkew int64 } // AcceptorOptions configures a network listener (acceptor) for incoming connections. diff --git a/lib/flusher.go b/lib/flusher.go index a18b309d6..c036f05aa 100644 --- a/lib/flusher.go +++ b/lib/flusher.go @@ -11,13 +11,16 @@ const ( latency time.Duration = 300 * time.Nanosecond ) -func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time.Duration) io.Writer { +type Flusher interface { + io.Writer + Reset(io.Writer) + Stop() +} + +func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time.Duration) Flusher { f := &flusher{ writer: bufio.NewWriter(w), } - if closer, ok := w.(io.Closer); ok { - f.conn = closer - } callback := func() { f.Lock() defer f.Unlock() @@ -27,9 +30,6 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time f.writer.Write(keepalive) if err := f.writer.Flush(); err != nil { f.err = err - if f.conn != nil { - f.conn.Close() - } return } @@ -39,9 +39,6 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time if err := f.writer.Flush(); err != nil { f.err = err - if f.conn != nil { - f.conn.Close() - } return } f.pending = false @@ -54,13 +51,10 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time return f } -func NewFlusher(w io.Writer) io.Writer { +func NewFlusher(w io.Writer) Flusher { f := &flusher{ writer: bufio.NewWriter(w), } - if closer, ok := w.(io.Closer); ok { - f.conn = closer - } callback := func() { f.Lock() defer f.Unlock() @@ -71,9 +65,6 @@ func NewFlusher(w io.Writer) io.Writer { if err := f.writer.Flush(); err != nil { f.err = err - if f.conn != nil { - f.conn.Close() - } return } f.pending = false @@ -91,7 +82,6 @@ type flusher struct { writer *bufio.Writer pending bool err error - conn io.Closer } func (f *flusher) Write(b []byte) (n int, err error) { @@ -132,3 +122,11 @@ func (f *flusher) Stop() { f.timer.Stop() } } + +func (f *flusher) Reset(w io.Writer) { + f.Lock() + defer f.Unlock() + f.writer.Reset(w) + f.pending = false + f.err = nil +} diff --git a/net/proto/connection.go b/net/proto/connection.go index c3b5d4f13..92c8fafc8 100644 --- a/net/proto/connection.go +++ b/net/proto/connection.go @@ -23,6 +23,8 @@ const ( // lib.Buffer has 4096 of capacity // 256 messages could have at least 1Mb of allocated memory limitMemRecvQueues int64 = 1024 * 1024 * 512 + + skewRingSize = 16 ) type connection struct { @@ -73,6 +75,9 @@ type connection struct { softwareKeepAliveMisses int softwareKeepAliveTimeout time.Duration // how long I wait (peer period * misses) + // clock skew measurement + clockSkew bool + // fragmentation fragmentation bool fragmentSize int @@ -118,9 +123,17 @@ type fragmentAssembly struct { type pool_item struct { connection net.Conn - fl io.Writer + fl lib.Flusher timer *time.Timer handling atomic.Bool + + // skew measurement (clock offset relative to peer, nanoseconds). + // skewRing/skewIdx are only written by serve() goroutine. + // skewCount/skewValue are read by timer goroutine via atomic. + skewRing [skewRingSize]int64 + skewIdx int + skewCount atomic.Int32 + skewValue atomic.Int64 } // @@ -183,10 +196,118 @@ func (c *connection) Info() gen.RemoteNodeInfo { DecompressedRecv: c.decompressedRecv.Load(), DecompressedBytesRecv: c.decompressedBytesRecv.Load(), DecompressedOrigRecv: c.decompressedOrigRecv.Load(), + + ClockSkew: c.Skew(), } return info } +// Skew returns the aggregated clock skew across all pool connections (nanoseconds). +// Positive value means the remote node's clock is ahead of local. +func (c *connection) Skew() int64 { + c.pool_mutex.RLock() + defer c.pool_mutex.RUnlock() + if len(c.pool) == 0 { + return 0 + } + values := make([]int64, 0, len(c.pool)) + for _, pi := range c.pool { + if pi.skewCount.Load() > 0 { + values = append(values, pi.skewValue.Load()) + } + } + if len(values) == 0 { + return 0 + } + return medianInt64(values) +} + +func (c *connection) handleSkew(pi *pool_item, buf *lib.Buffer, tsRecv int64) { + ts2 := int64(binary.BigEndian.Uint64(buf.B[16:24])) + + if ts2 == 0 { + // ping - reuse buf for response, fill ts2 and ts3 + binary.BigEndian.PutUint64(buf.B[16:24], uint64(tsRecv)) + binary.BigEndian.PutUint64(buf.B[24:32], uint64(time.Now().UnixNano())) + pi.fl.Write(buf.B) + return + } + + // response - compute and store skew + ts1 := int64(binary.BigEndian.Uint64(buf.B[8:16])) + ts3 := int64(binary.BigEndian.Uint64(buf.B[24:32])) + rtt := (tsRecv - ts1) - (ts3 - ts2) + skew := ts2 - (ts1 + rtt/2) + c.pushSkew(pi, skew) +} + +func (c *connection) pushSkew(pi *pool_item, skew int64) { + pi.skewRing[pi.skewIdx%skewRingSize] = skew + pi.skewIdx++ + n := pi.skewCount.Load() + if n < skewRingSize { + n++ + pi.skewCount.Store(n) + } + + var tmp [skewRingSize]int64 + copy(tmp[:n], pi.skewRing[:n]) + pi.skewValue.Store(medianInt64(tmp[:n])) + + // schedule next ping only after receiving response + if c.terminated { + return + } + interval := 5 * time.Second + if n < skewRingSize { + interval = 100 * time.Millisecond + } + pi.timer.Reset(interval) +} + +func (c *connection) skewTick(pi *pool_item) { + if c.terminated { + return + } + c.sendSkewPing(pi) +} + +func (c *connection) sendSkewPing(pi *pool_item) { + buf := lib.TakeBuffer() + buf.Allocate(32) + buf.B[0] = protoMagic + buf.B[1] = protoVersion + binary.BigEndian.PutUint32(buf.B[2:6], 32) + buf.B[6] = 0 + buf.B[7] = protoMessageS + binary.BigEndian.PutUint64(buf.B[8:16], uint64(time.Now().UnixNano())) + binary.BigEndian.PutUint64(buf.B[16:24], 0) + binary.BigEndian.PutUint64(buf.B[24:32], 0) + pi.fl.Write(buf.B) + lib.ReleaseBuffer(buf) +} + +// medianInt64 sorts vals in place and returns the median. +func medianInt64(vals []int64) int64 { + n := len(vals) + if n == 0 { + return 0 + } + for i := 1; i < n; i++ { + v := vals[i] + j := i - 1 + for j >= 0 && vals[j] > v { + vals[j+1] = vals[j] + j-- + } + vals[j+1] = v + } + if n%2 == 0 { + return (vals[n/2-1] + vals[n/2]) / 2 + } + return vals[n/2] +} + func (c *connection) Spawn(name gen.Atom, options gen.ProcessOptions, args ...any) (gen.PID, error) { opts := gen.ProcessOptionsExtra{ ProcessOptions: options, @@ -1569,7 +1690,7 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ c.log.Trace("joined new connection %s to the pool", conn.RemoteAddr().String()) } - c.serve(pi.connection, tail) + c.serve(pi, tail) if dial != nil { pool_dsn := []string{} @@ -1589,17 +1710,23 @@ func (c *connection) Join(conn net.Conn, id string, dial gen.NetworkDial, tail [ } pi.connection = nc nc.SetWriteDeadline(time.Time{}) - if stopper, ok := pi.fl.(interface{ Stop() }); ok { - stopper.Stop() - } - if c.softwareKeepAlive { - pi.fl = lib.NewFlusherWithKeepAlive(nc, c.softwareKeepAliveMessage, c.softwareKeepAlivePeriod) - } else { - pi.fl = lib.NewFlusher(nc) + if pi.timer != nil { + pi.timer.Stop() } + pi.fl.Reset(nc) tail = t atomic.AddUint64(&c.reconnections, 1) + // reset skew state and restart measurement + if c.clockSkew { + pi.skewIdx = 0 + pi.skewCount.Store(0) + pi.skewValue.Store(0) + pi.timer = time.AfterFunc(100*time.Millisecond, func() { + c.skewTick(pi) + }) + } + goto re } } @@ -1636,6 +1763,9 @@ func (c *connection) Terminate(reason error) { c.pool_mutex.Lock() defer c.pool_mutex.Unlock() for _, pi := range c.pool { + if pi.timer != nil { + pi.timer.Stop() + } pi.connection.Close() } @@ -1645,7 +1775,15 @@ func (c *connection) Terminate(reason error) { } } -func (c *connection) serve(conn net.Conn, tail []byte) { +func (c *connection) serve(pi *pool_item, tail []byte) { + conn := pi.connection + + // start skew measurement now that serve() is running + if c.clockSkew { + pi.timer = time.AfterFunc(100*time.Millisecond, func() { + c.skewTick(pi) + }) + } recvN := 0 recvNQ := len(c.recvQueues) @@ -1698,7 +1836,16 @@ func (c *connection) serve(conn net.Conn, tail []byte) { } // handle keepalive silently, don't count, don't queue - if buf.B[7] == protoMessageSoftwareKeepAlive { + if buf.B[7] == protoMessageK { + lib.ReleaseBuffer(buf) + buf = buftail + continue + } + + // handle skew measurement before queue dispatch for timestamp accuracy + if buf.B[7] == protoMessageS { + tsRecv := time.Now().UnixNano() + c.handleSkew(pi, buf, tsRecv) lib.ReleaseBuffer(buf) buf = buftail continue diff --git a/net/proto/enp.go b/net/proto/enp.go index b36dee969..01d7a9f5a 100644 --- a/net/proto/enp.go +++ b/net/proto/enp.go @@ -85,10 +85,15 @@ func (e *enp) NewConnection(core gen.Core, result gen.HandshakeResult, log gen.L conn.softwareKeepAliveMisses = misses conn.softwareKeepAliveTimeout = peerPeriod * time.Duration(misses) conn.softwareKeepAliveMessage = []byte{ - protoMagic, protoVersion, 0, 0, 0, 8, 0, protoMessageSoftwareKeepAlive, + protoMagic, protoVersion, 0, 0, 0, 8, 0, protoMessageK, } } + if result.NodeFlags.EnableClockSkew == true && + result.PeerFlags.EnableClockSkew == true { + conn.clockSkew = true + } + if result.NodeFlags.EnableFragmentation == true && result.PeerFlags.EnableFragmentation == true { conn.fragmentation = true diff --git a/net/proto/types.go b/net/proto/types.go index 1cdca902c..431c68077 100644 --- a/net/proto/types.go +++ b/net/proto/types.go @@ -46,8 +46,8 @@ const ( protoMessageF byte = 202 // fragmented protoMessageP byte = 203 // proxy - // software keepalive - protoMessageSoftwareKeepAlive byte = 208 + protoMessageK byte = 208 // keepalive + protoMessageS byte = 209 // skew measurement // TODO // protoFragmentSize int = 65000 diff --git a/node/network.go b/node/network.go index a426e0784..b214fc25f 100644 --- a/node/network.go +++ b/node/network.go @@ -52,12 +52,12 @@ type network struct { handshakes sync.Map // .Version().String() -> handshake protos sync.Map // .Version().String() -> proto - cookie string - maxmessagesize int - softwareKeepAliveMisses int - fragmentSize int - fragmentTimeout int - maxFragmentAssemblies int + cookie string + maxmessagesize int + softwareKeepAliveMisses int + fragmentSize int + fragmentTimeout int + maxFragmentAssemblies int staticRoutes *staticRoutes staticProxies *staticProxies @@ -1413,21 +1413,54 @@ func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOpt if v, exist := n.connections.Load(result.Peer); exist { conn := v.(gen.Connection) if err := conn.Join(c, result.ConnectionID, nil, result.Tail); err != nil { - if err == gen.ErrUnsupported { - n.node.Log().Warning("unable to accept connection with %s (join is not supported)", - result.Peer) - } else { - n.node.Log().Trace("unable to join %s to the existing connection with %s: %s", - c.RemoteAddr(), result.Peer, err) - } c.Close() } return } - // Join handshake for a connection that no longer exists, peer's pool expansion - // arrived after the connection was terminated. Nothing to join, close silently. + // Primary connection: announce pending BEFORE heavy work so pool + // expansion TCPs (PeerCreation == 0) can wait for registration. + if result.PeerCreation != 0 { + acceptPending := &pendingEntry{ready: make(chan struct{})} + if _, loaded := n.pending.LoadOrStore(result.Peer, acceptPending); loaded { + acceptPending = nil + } + defer func() { + if acceptPending != nil { + n.pending.Delete(result.Peer) + close(acceptPending.ready) + } + }() + } + + // Pool expansion (Join handshake, PeerCreation == 0). + // + // FIXME: workaround for a handshake design flaw with TCP pool expansion. + // The initiator starts dialing pool expansion connections (Join handshake) + // immediately after completing the primary handshake. These arrive at the + // acceptor as separate goroutines running handleAccepted(). The Join + // handshake (2 messages) completes faster than the primary handshake + // (5 messages), so the pool expansion TCP can reach this point before the + // primary TCP goroutine has finished registering the connection in + // n.connections. Without the retry, the pool TCP is closed, causing + // broken pipe on the initiator side for any pool_item using that TCP. + // Once the handshake protocol is redesigned to properly synchronize pool + // formation, this workaround can be removed. if result.PeerCreation == 0 { + for i := 0; i < 3; i++ { + if pe, exist := n.pending.Load(result.Peer); exist { + entry := pe.(*pendingEntry) + <-entry.ready + } + if v, exist := n.connections.Load(result.Peer); exist { + conn := v.(gen.Connection) + if err := conn.Join(c, result.ConnectionID, nil, result.Tail); err != nil { + c.Close() + } + return + } + time.Sleep(300 * time.Millisecond) + } c.Close() return } @@ -1457,7 +1490,7 @@ func (n *network) handleAccepted(a *acceptor, c net.Conn, hopts gen.HandshakeOpt if _, err := n.registerConnection(result.Peer, conn); err != nil { // connect() registered between our Load and LoadOrStore - conn.Terminate(nil) // fix: cleanup the unused connection object + conn.Terminate(nil) // with deterministic ID, join TCP into the existing connection existing, ok := n.connections.Load(result.Peer) diff --git a/testing/tests/002_distributed/t011_fragmentation_load_test.go b/testing/tests/002_distributed/t011_fragmentation_load_test.go index ac9d82f42..b9b387bfd 100644 --- a/testing/tests/002_distributed/t011_fragmentation_load_test.go +++ b/testing/tests/002_distributed/t011_fragmentation_load_test.go @@ -17,9 +17,9 @@ import ( type t11receiver struct { act.Actor - target int64 - count atomic.Int64 - done chan struct{} + target int64 + count atomic.Int64 + done chan struct{} mismatch atomic.Int64 } @@ -71,11 +71,11 @@ func factory_t11sender() gen.ProcessBehavior { } type t11sendJob struct { - target gen.PID - size int - count int + target gen.PID + size int + count int noOrder bool - done chan error + done chan error } func (t *t11sender) HandleMessage(from gen.PID, message any) error { @@ -285,11 +285,13 @@ func testFragLoadMixedConcurrent(t *testing.T) { func setupFragLoadNodes(t *testing.T, suffix string) (gen.Node, gen.Node, gen.PID) { t.Helper() + uid := lib.RandomString(6) + options1 := gen.NodeOptions{} options1.Network.Cookie = "fragload" options1.Network.FragmentSize = 1000 options1.Log.DefaultLogger.Disable = true - node1, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11node1%s@localhost", suffix)), options1) + node1, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11n1%s%s@localhost", suffix, uid)), options1) if err != nil { t.Fatal(err) } @@ -298,7 +300,7 @@ func setupFragLoadNodes(t *testing.T, suffix string) (gen.Node, gen.Node, gen.PI options2.Network.Cookie = "fragload" options2.Network.FragmentSize = 1000 options2.Log.DefaultLogger.Disable = true - node2, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11node2%s@localhost", suffix)), options2) + node2, err := ergo.StartNode(gen.Atom(fmt.Sprintf("distT11n2%s%s@localhost", suffix, uid)), options2) if err != nil { node1.Stop() t.Fatal(err) From c858e8598922a40fe9f77e193e4fffc656d70c30 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Wed, 25 Mar 2026 18:37:00 +0100 Subject: [PATCH 065/122] tracing prep: add network flag --- gen/network.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gen/network.go b/gen/network.go index 1194da7d7..1d252a950 100644 --- a/gen/network.go +++ b/gen/network.go @@ -412,6 +412,9 @@ type NetworkFlags struct { // EnableClockSkew enables clock skew measurement between connected nodes. // Both nodes must have it enabled for measurements to work. EnableClockSkew bool + // EnableTracing enables distributed tracing support. + // Both nodes must have it enabled for trace context propagation. + EnableTracing bool // EnableSoftwareKeepAlive enables application-level keepalive with the given period in seconds. // Zero disables keepalive. Max 255. EnableSoftwareKeepAlive int @@ -459,6 +462,9 @@ func (nf NetworkFlags) MarshalEDF(w io.Writer) error { if nf.EnableClockSkew == true { flags |= 1 << 16 } + if nf.EnableTracing == true { + flags |= 1 << 17 + } binary.BigEndian.PutUint64(buf[:], flags) w.Write(buf[:]) return nil @@ -482,6 +488,7 @@ func (nf *NetworkFlags) UnmarshalEDF(buf []byte) error { nf.EnableSimultaneousConnect = (flags & 128) > 0 nf.EnableSoftwareKeepAlive = int((flags >> 8) & 0xFF) nf.EnableClockSkew = (flags & (1 << 16)) > 0 + nf.EnableTracing = (flags & (1 << 17)) > 0 return nil } From a10314a5766c5bbde62bf52be3168a3c3b93f5b4 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Mar 2026 08:55:42 +0100 Subject: [PATCH 066/122] sync --- lib/buffer.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/buffer.go b/lib/buffer.go index 47b05f2f0..56be6decd 100644 --- a/lib/buffer.go +++ b/lib/buffer.go @@ -5,7 +5,6 @@ import ( "io" "math" "sync" - "sync/atomic" ) // Buffer @@ -25,30 +24,17 @@ var ( return b }, } - buffersTaken uint64 = 0 - buffersTakenSize uint64 = 0 - buffersReturned uint64 = 0 - buffersReturnedSize uint64 = 0 ) -func StatBuffers() { - fmt.Printf("taken: %d (size: %d)\n", buffersTaken, buffersTakenSize) - fmt.Printf("returned: %d (size: %d)\n", buffersReturned, buffersReturnedSize) -} - // TakeBuffer func TakeBuffer() *Buffer { b := buffers.Get().(*Buffer) - atomic.AddUint64(&buffersTaken, 1) - atomic.AddUint64(&buffersTakenSize, uint64(cap(b.B))) return b } // ReleaseBuffer func ReleaseBuffer(b *Buffer) { b.B = b.original[:0] - atomic.AddUint64(&buffersReturned, 1) - atomic.AddUint64(&buffersReturnedSize, uint64(cap(b.B))) buffers.Put(b) } From 3966e8449375d65cd7268ddd54dd9da42cf24469 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Mar 2026 13:05:05 +0100 Subject: [PATCH 067/122] sync --- .github/images/benchmark_ping.png | Bin 0 -> 596561 bytes README.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .github/images/benchmark_ping.png diff --git a/.github/images/benchmark_ping.png b/.github/images/benchmark_ping.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff33dce6a8a75239f4abff27fc03c51a0bcd0d8 GIT binary patch literal 596561 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%0D&U8e($SeWh(T2}?ml*- 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
{-{o*NTy7-Tk9 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%0DPgiEdMO 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

!MB7SYxWfBzFp{{8m<-@Mjs|C9MJ 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 Date: Fri, 27 Mar 2026 13:06:57 +0100 Subject: [PATCH 068/122] sync --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93d30c5bb..4b6a5d477 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Examples demonstrating the framework's capabilities are available in the [exampl ### Benchmarks ### -On a 64-core processor, Ergo Framework demonstrates a performance of **over 21 million messages per second locally** and **nearly 5 million messages per second over the network**. +On a 64-core processor, Ergo Framework demonstrates a performance of **over 21 million messages per second locally** and **nearly 5.5 million messages per second over the network**. ![image](.github/images/benchmark_ping.png) From b105ef09c1ba1006dc0da9861f3dcc008665dc66 Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Mar 2026 13:45:09 +0100 Subject: [PATCH 069/122] sync --- lib/flusher.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/flusher.go b/lib/flusher.go index c036f05aa..c15c781c1 100644 --- a/lib/flusher.go +++ b/lib/flusher.go @@ -8,7 +8,8 @@ import ( ) const ( - latency time.Duration = 300 * time.Nanosecond + latency time.Duration = 500 * time.Nanosecond + bufioSize int = 65536 ) type Flusher interface { @@ -19,7 +20,7 @@ type Flusher interface { func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time.Duration) Flusher { f := &flusher{ - writer: bufio.NewWriter(w), + writer: bufio.NewWriterSize(w, bufioSize), } callback := func() { f.Lock() @@ -53,7 +54,7 @@ func NewFlusherWithKeepAlive(w io.Writer, keepalive []byte, keepalivePeriod time func NewFlusher(w io.Writer) Flusher { f := &flusher{ - writer: bufio.NewWriter(w), + writer: bufio.NewWriterSize(w, bufioSize), } callback := func() { f.Lock() From 109a1d33ad6847cf014cd2c17a3addc339d2f94e Mon Sep 17 00:00:00 2001 From: Taras Halturin Date: Fri, 27 Mar 2026 14:23:42 +0100 Subject: [PATCH 070/122] sync --- docs/.gitbook/assets/observer.png | Bin 1058190 -> 1292613 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/.gitbook/assets/observer.png b/docs/.gitbook/assets/observer.png index c8d0b0dc343d1ecf8c17939e2cb2afc3f102f917..f3166965cc4aec3956aff3848e3950c45df43495 100644 GIT binary patch literal 1292613 zcmeFZ30PCf_AiQ!ii&_rD*^#jRJxrI140N%q_IIoNZZ&=iwp`%7-S3(2t!mW|C znG+EOQ2`Z^F$oBYC?p`rn1KKi#v~9RWZZ8Jy)#+?+lhSTPi87sqnS2`Q@mM z&6Zz6gS>q&oL5phl6W^=Fv){R|ZEgxHcYr{{f_qXU>xU&7qp;aa; zR={6YUiP>CdHKg1B{zQP`N7lf`~C+#(#w0ceW?E9dEN}-%&Hn`t0-2OYmTD@(cmHm zmR}1O5|n<~Q~7Jr=C0*iPCvNy_R7iwckVcCUPxD3w(^i(Y*Lj~)t?*n^j80(DW)g=Lv@G|X+@tymw*I#-> zM5r5l`Tfs;Hpq`34CgX^2}Opo)2*hzIqY+OJoti~q_g$N_VgQ7Q2;kY7W8q`?xybN zwkj~2O`GEJHnWU4`iI0{UThD*cUs(B$QS45f_MEYaAICs>Ag!hW30+JW-sz&#UZR=I-oK>&%U%H!!O#o=C*nA&EmdyN_j* zjPKoj&~sZt@r{pvnmi$|+MahwbK=@#+Sb#Gbn;D$Csj9+D))be1sh4Uj{Ko%_T}gk z*23lc1Bp42zfn%Ef9ztvE9Lhus*QP1Dy__aH*>xem!pZz{|%GTtd^>eS*QB_q16kA zmWL`SFVAyVe|TtZRA#*3a&w}$UF zv?-b1S4p}Ad%jG)ZbhV$!8)bO))v>l3)!OGvdrq%vX__Ewy4~!3;kvJu{z7=t506k zJEPU3qJG)%{`#Ed+`6BGH!_rPb%t%L@pZfRDb^^gQ*^Wt}VLtb_85_kWjm zR_DU<)AdegcD7tL9I%KyxaSJDUL3r&cICc=rvu8t$}#GcHS9}pj*J~%YmLGwBy2kj)@^;)XbY()G=jP2SNg6xXYNm3|j-0)B z=6A1M`=$HUGJbE_dtA#~NvLOEuj4uOg7t^`!PUDPX-%8XetaJNe6B~e2i~JUsRB{A zYdSS#6>_%noa@fOt$}8Nx+UtkP2HC!-l+{vMhp+`)|t+hm($%VgRzhZqfo zrgid}pMtkuS@-Lz4L>c*OL|TU&I(Rzv){bUZ^Pb1R^t!bNEvpn_6&y$JKc@u*CiZr z+3tVG_{Wq#kGeSSGWvXH-!1(#R#8z=W>Hj8>o1x`d!2SW!yiT*Ew-P6p31&p=beVR zeRtSwm^@rItTK%Ie$Cq(8x9@K`{4)wA3pyn{Il>+^!UkeyYLiCkJuvoBYeEXVXj-} zu$sNvy?2o0nB)V=`8wTZ60^jt-?J__l#Fa>J=QvuB{Eehf9yhYIpNal^0a*3->nOu zm)!mOlX};Pzm^~W6S9=)@blx5lLznGxmhzE$cLu#I6hsb>U-0E{|SD?zff(|XQFa! z`{v~mYN(yHfj4Y!xO%N- zZK<}pj<)VqoukRGH|Ls_FijiZ}xsw(PVBgMHF7)Ki7%>Up4FWZXG$ zUjFCnAKAH#+(yTmTz!~7JOQp{VGgH;zrb>;PF6D_9#vke+!r1Y8aw38-x=J`i(u!D zBU@u1McD&oxX5SMK{JzZ!nkwb_Z2tb8SjqvXC18b5*`$~Pb)9zieta?ur9i9&NL^R z%CELLS6cU^b4VxdwHtfh+;uqUK*Istxww`aANsP*_BejueO~jWQ(3D0s~xBAbU}u4 zR>1UrjrP6$3QH8#ItW*uTmKRfdIWiz_3(b4=UCP!TXFo$-QC6&2SgpRD`Gn>pS`#C zRNlj+SL`Y^M{NhvuV!4Wy}I}2ajm@`o#h$jk=zYFNBi#Fdo*INnm)fr)$Mf<%r~lQ z#zQq{%`sJ0=@HjrpGsd*xh+TW?)KgdIfKzki43C&c zjYSWi4Nv&7#&@G&z)3}iAZyla${*1c=#g;R=oAh|1|+eMTpo!ZF?9<9e0tvZ{82kC zFR04imtJ*us^@s$GX~?7{wdb0x1JxX_j>F;u#0zckSgzL(#UU*5DQHK4e# zOUwL_T9le{vUYN=L$iZkQ$uQnsnoQa6m0cE^l+^CgOg=p7jb9qJ}X4bPM~Gr)L5?q z`v%M0i#@HMi?$@xgxmT{uU=P8-*?T`iv7+Hj%^lwYW~PdPxUzK?pr$^QqIYemP9(Pg}F7MD$!J|r7x zZD1tWq~1fkL+*=vAbvPm#OZj#zCd_7F*|DYd1Ghz)TzlbJ7z7FeJMJxvpvoU$1I~aV*fG{M%=$n6PZG`#LMh zGJRKYC41xiA4k0%9F%r}*Q=D4FVj(40bVTw59Bi4e_q=z`$0*0>Hc?0N(sJ7%fFU! z1ka0~Ti~%+=dZK!ooh-eU}^(+MBe}IAEnnW+*kg`^=eNrPs!TJ=IBxI?Bo@C{(K7(1TO>5hn?LL8E_#GYZ-~ywp79ryk5L*ylu-;kuZP6wm%$x*$<8ZirIOx8hP>it&3X7^v};HS=plE91qs|BEdC67uGAHRPI~FTeN!>_~|3Vf0Dx4651UXZZ{82fV*{29Gs=>XjS4LK2a@82pfjLHoEDxa#W znC#fK)D;UKAwB6c9^P~Aul_9p`%CPo50@08RybfMKOjB3B(sGY5QoeDBIC2Osl5tj z9Gg1j`ft&O1+L|DKz|A)3aTK*{6n=Cn&5&FgTpMJxbExbWo(}UDSKA_V=D__UP67D z%7(Fn2qJ^0|FH{+gXRemrs8{14U19*uwl|x`O{N>_k;#y)Od!5+AM!k&YzHdzNK+E z)`M%16!*DL6t3`lukwIWD%7y0`b|kK31-8}C)nL$m3)u#`Pf{l&djC9V4e8(QWq(O z=AkA&)Ctz9A9XGUNt9lT*)lG*1kTJp?E*WKQd2W+WGK}ueLNswRvAocCWpHj*(qN$TFH5Dy>N!)^K8NrrnBG5WR;!z8x`qcFSqXI_KTcEYm3lz z$Q~n|iE77`m21&!-`tKD)Fa#f=nfAxJrns2`kTPNsoA%|^`AMVtV8;_HlO9dT7}`8lx2yV2J`SC*c0Pz-aiwT03SnmTt!?3(t+SZ=4-%{Ts@l6Z9jfelBxu6XS z!D*O1pJ?X$rBR}JlA=o;wKaVYfm~_nh-@DKCy8O=_eJyf$c`@93a z`e}I=EOvlJB@p;;UhN*aUW$M0u{HKgSPB#OmOWQVxRJRUlxYEm`PpS62N}#~Q~x8y z`0!Fq2jlZ7Nr02$yZAIQlR_Z~zbXwotj^f8Dd^oP{(?i0=~xJ9$Q=3%H_6(K%<6Q- zO=>rmu;*T<#NCoG*S@lqykXA0ra?znkY4cu0=Pb<3ng}Qf9{TlnqIi@>5`qL-P3*P{~iRhaa{f|2i{1b~WDLY}ACRy-TtZ6s8+Z4K` zG8^DOlc%Ai)QPkcf7-D z_Kf7Z5t-{4E^_(kI^Ox-I&4eKtse5ovr8(`M9eSQ77|3i<#@}MpvmgR6n*P!nycrG zE$^aet)FHB^2mi;nE!w^FIXKD#t;^`V~a(5KzmG5N;Ip}zhsX1^94jsdk8%n-&)Qp zyI!0Cwd6%Pl~#2{Z+bBoY}M_W%+Th#43fwI0Fg7+RIh zMGnH{rYH#6NgmK@+0@bE!BGr9^Qgj=|K<2X!}gOeaO&VTE*)aGAip$y_1f(AEE)-K zgn;xw-#A6T;f3>HtwxyF{(??o@c7k!DJHewN%q~;X@7X3%0nUp`?x{ZEgnPDbR-8a zu2XvrA}-4hRIfy{7w^;%Y6z1W@cKAyxA;Q->O%KQCY6brPslw(O)9DH5M6OHX7JcN z18IZfa}V3@fwAZ}MOuNPAW^FPtWl3~zQ14=!Rb`3kXA^W6wfs$)7#A=B};tB`{iDQ zp4IaoM|G@X(H3)WrW8|(7pTeQ((_?zM2b-ko)ZB?06qUX>?pKEscdrW1!8rSr*!_Q z0va!#HAgdRy(EYHavMB24-=G2@eLIP!Wvc)n^8)`SNl&a^-@g806(sIR!%D&lzmsi z{8B8P`G{%>DIIz$eYSO_)P1J2xawx9UktHGT_x0bGpoF2;mQ2Gg7Pu8Wo6L{Y<0I~ zH^*pF8y(y7d|yb4|1c5F9F?SQMR7BNVkdGmRWdnok?R~n)ft^CT6--;>uVh8R}e!* zsoGs3h5jWC=*{XZY>SgQSIjevV9Et&=sA%h&C}@?O=h9=!oVF^;v;#A5rL zA)P9&lXpdMda++<)ZM62TG|)esmZNMwSO4=(T5MxU2lOmGa@^}$IAbhpLZEpq zUIY<#wnkAv6dcN`2WrHUH+Joyg(NeCMY?W)$uJipEDp-W4sL-mG&CL@rCrLF3_SRm zi}dUs%Y2TpnlovzwkiIR-7dbsKlOW7690HVn%982VbC`=8F z`IbZ+>P2`W*40oHGj7{WSSyA##Y~*$=2*O6D{6@Mxq}@jKvw#+SEcrZ<9GhmNhxqQ ztX|xkU;)vKSPi4&Kok%)dZe+2)KlFEE4dww49}lHU6bW_QRa%Vj*xTLq#SG0W>~P3 zf$OVLhTWtkLUTT;5b6C#Q*KF>I_j)NB;5qf%;DC6C?F~VJIF*|a2telzekX&+vf~y z;%FvpNf*pW{Xm0Uum!YHRu*aOa|r`GJeRmS`kj*j^x2SOw`&4vKctqMQ5Z-QGVLa- zrJQ;qY?^2E`kPvPQ>*`AwUYeHEXcFZv0;Dj@wv@0++x2ANl?Ok>s;PalQpEzwr7NM zolQh0L;FN)ClYITvRy=;7i(}Sw1rTk92X^SaGmb5dQ0T=#0s{Q(>V2=?H4-_2~&zx z8ic4;IKKyhD;x7ylfUz6zZ6W%&R2`jHAUtw*%nQ) z!|xhlE#nysY}>(a>2LD*rVro7!?*e1|LJ^~VG}e{)D+V++@i!uZe-lH;ufj2YD}XM zCT89j1-2p!BHop+-HuLxx$$eG$5aWA%=kTJad&Zirx-J7Q4qM)2Exyzj{+{!sjFs0 z5&%dh&5kKb;5bVI?n|Y6yk!`9}RWc2!bQEOqiOZZd2>scmqK$94|7Gnc~o zd{Q-`FcE8s>KQUJ^DY6v(#uJ|UPUtqy5m#%LLZBk^9A7}ZI3jN(<~sCI<+ybw>uc} zD$*|(7B&`-u2qx*EVcQ3(fcS<2)_5niIzNjgP6g^?HPZiv^{#*N=KbM`R7*(;2w>H ziHLjpfK{TCHsd1 zE7Z@OotI(Y0%v4rhg)lSO0=`Aw6lF=$A?;Y5>cxpd_zdZ?S>WS`u8Om?OFM$l;`8s2Zc_+Kx$0v)MBXg%)#QFyvF`=|TMDC8Nimm#wFM{(T!MhO9cpWQOP+YOO144V~yhbLSmUz#B`3vRffr82HglZoam>3 zZUX;U!~~cY@%sgC8|9J8# zVh}NIeE6MWZ42QiHr5 zw1R9Vdr3HlBKOCT#(vgF=!)$ufDas!Sko^}M0HhOLvCi_)|pouy};CrM0Hs)N!qgq zQgc`Wh3jY%Ph7(X2#UG-g~|IUC!{&4!izh5O?sD2;CleQdch)NbbHji7|#AOzfJvi z8JsgO$4WM!Bt2!Z08g5ZQDKPq-A32AJDz!QBeeqAD0b`(V~EvSo)p7IS-}S=gvejj zhog>;^uSnG`$cpdX;4)~BVMZL6=~4bEBOY*Kb520@4zBba3ER1Pk_8@=39PVDh3=!8r=M#odwl{~h!KRiT(Jd#9dx z6EnZNYQoJv*Gtc}4bgR6ls#cVCVqi$h(1{E`|f161-?i=F6U7va{YoC0kuyuak7H$ ztYqM$-uuu=F+2QXx^j!Pkt%)>=84DL>w6HHlZcC(IlIr5 z+geB*g3X%he-PTIF^*`sayer7c1Hx)nTN6*A%Q`+jJMARbq($B}_k#L=}=X384{yy1`6ZuCLX`?)8WtEH$X$WSdTYzf2^C%jz_V z>xYUeQzTInR=F+5YZXmbV*$PpH)$O=(_%`zF>zi0``iRJmmkA#B;_!v4GFSy7#;N6 z@WUE6Xbp=K@p$ueN^k|!2qNdlu`JO>P|Z>xEAVvW}V!>{yc@+MO=p$WZ;RY zsf{2XAksJ_ULhT>OM|^I(V@@BcI73qRMcF#f_LUR6XuEpi(9BkBA~8PqW^28U@FKT z9IDxdDyMO8?YKH7M{=WT1tl{AA04-eIQI;Os%?5kL(5Z$Voj+8=#(oM9hk~$l#5@z zOsh?tkeFjmMTsukamAWM_+zkpz%hyg=EdN+n!d*n8M8NWao?|H8^lmAc3MZy3P7>* zNpeN+*Po%iRcutu=}8fq;BiMNUqejEg@3;nKc1VQQNd>~j%QKiv3Ys)!Yz`VvV}`l zChFNOPbK2HoQA2z;Vf0ah<9QE2yz%hHGUsOy@+XAU!PydidqO>9M5zLA*Jvf8v(U*W+KJt^fb!ehU} z%fI`-313=E=rNj4s(m491-n9?*_;<~7vRY=vu#kTMEMJ)253>f>Vp-n>s6%tX6ti0 zVVyZf-tY8mxtUH72X(Ba;>5FRGhWS5rjY+mVFgMff&#fNj#l7R6rG>gtx>1_bFod8 z=k|rD8zbER;Iv%|u7|wp%nUyXzBPu!REkKj$gqh!$K{Xrg%L#U8r6f$tF!Zvh5P=f4nSHG62J$@B99nh)Fhvvzq9A12|52?}=x;W%PMcq&GvngW!h_FbWd5+wOt z><(@jXnrO8Ck#%|caz0o`zLOs?ktBO4G=2Qxw86GXvn$WJ=L+z$tAFq0<0)Nrh(l; zXh9H?l?iX-J8%}bmY}s-EmhGc?q`NMmlOH!_{i1O_cGE5N&`2)OQA=Zk$T&q276&; zI+<#Oa1^dKQ)`MT?+i5()^!$u!%4lmk(g$cU}-j!kC#34MpSq5c+@OS7B(?6`m>$h zLpt7XWJ5(4Y`W8aFZ6MI$s?l8)O#8Ui~_Qn`&D=$tRzI!EcAIfEwRwuFB%Y6yfuoB zr+2=u@3J%^;){xb36yjh-n<9uH+;rFR})R{TyijIwAIuTPk__NL{8-Rqt}a`inxp5 z5;aK&*5kr$bTTeqa(O7v20q99lh~58!r(qG9+7XW{(6a}fF-Yo5?Oar`=4AaxldF^ znP=#aZ^!?|XaAz(19gbMGTJs7a-kSISd`wkXuARcKph?jbeZT`O5idNdilt$Qwfipwq2Y#?0 zq_`i%ec<21ts4AQcr#Tiey)A^zJKcpIbH>VaF&nO5p(JFncgRqi!Z5qt9uZAGFo#- zi{c}#^>e)>F)ENz9kR2iFachimztS8TL(wW=0#`}xju)%R8g~v@)~z`^^>_%8t|sp z3n{tz%L;W|gZaStZq|URekQ*MMu~S)+xH$J6{YGn)z_R+XVoQOCn5Sde!=x~0L$L$ zP1#rwM`x*2<>JU9@_Q*s*?+gqt%M{Q}Ed0fOI(o>x?cKx$P-2Gn9Knm{Y*QcL*c zMnkJ?#ikMtd=Y&Dknr8kn)j$iG=fdZT(QK#^X|@p_6$(iqRUIdjwUcH)LARAf|bY| zFRtLPmWbR3*ApEGs@(#;CE+jbeV*%1u7G=jO=0cETkoQmEA^Y|Q(7KKy<0(Ne5wOOD^jXpk|BMSs>3 zqCtwcG(&1hw&-+2(Bu+oBG8y*E|SsxJOxC;Yh|nL$vEmp7t_Tc?G4xx_YI@P;b>2P ztHS8VkD5Y4)vcfn4S6QNDi`e_2!Wk#qBh+t8Y3TPaNZ_{!h$qQBT{#QJDX%_Iqsyv zc$l~8cy5DhC_cF;FW$}oTpRhfH<+a7xO@4vU;S7$4tv5zX;{6_8Fnt4SMZ5L{dY0* z6=t26TaGd;r9_>+l#Y*i++7JOnVB*Crn}11pRS`9BED#+jqV6Kr;c?i?7p5tA+u9r z32YA2`Ew@6kV3qR-2`pp2}N^mrco;saKp)wItst^%u5k+4}h%7`Y~cf2{!T;tQiLc ze>qeO9n_?_MZMdOZ`RFhaP1y5dypT*2X{EQO?z0k%?G^}b{l72I%wHMOx*NWHBp=^ zY#l#o;YyG*(InA*#&%?XcQ`(IbhKYO)q^BVt|BL>t{%t^=#7tf<}V zctExPVB5;f+mV*h0OwfD@Ia42~hLEtkhQN(@4t;mB&@J2Im9_VF zB8|u9eBiPF7bi=QDjcX~Rm}z#`|+NF6#G_bj%++qKMPJX^V}~_$rSC*pd;i`cFTL2 zLPRZEQAJ{-#Qnn8MwTNR;u&8~HFhQumFavX@I641h4)@X1LVCyB%RH_XzL%!`f56?J zroTYc*59jxckw48@t324v6aL@?Yr})RxYNquez*aXP0*a9cor@p}VGhBVYN9`W8n? zMpuJYSl!4Qn3H`S0-yG_4j18UyQV9EHWz$PfBdSD)BYf@uzX}J->6bS3LN;6c)}Om zkpHs{+P}5K4jn8h=0f4K6>Pv-@wvP~MshiXg z#b#&&1i17FQ$|lG9gEian_1AT{QnEH-x&Nq?QUPM@6%G#a9s)>6^My@03DaoKdhh5 z@4>UePa|~_>ji^BL zg;@jcA>a})gd6|{R0e}SX>>D{e^yHhXnZH=h-XQLVLrO4<8yR#JTjes6oNE@W~4DB z!^qCM&g=CfcQA2|Y-O#72Bzs22`>8+qLNG2t6&SXTcLbA8+mZ@=2xArp0q*{)abq5 zz)2gsR*_~0`v`p_YpjULq`SUK?kp8Jq67FS5;d}(ZS}tXsqMIPWMSbwR$~qshzXot zUaC{%!O11M;5D&biz~+42P{|A@3w)2;3 zZ|7FMfg{XDpk5;WtS(ycPhwI#f~@`(dJbF( z2A(s1uiKlsySBs03ki(?9I5}4F*Ae;0A^rVS(U6ebzIzG<|#OtOT1>EI~4uq1e70@ z(r!1gS#4CuN&BCfsnK*_Z98E0|7VmtJF=qYZ0WiNDN%<6(qBh1Vw$DYF&0Y4wCcsD@jbGKZ|d z7@6v^IKNnxnCJdZ`b?IARta4K!~!8tachu05K zem{5d?q9~Npg8m_{4M%KcY&287U(JGPk*(ti4pDm?@p1VFZ*gHTT|{h-O&M}#<5WmQ_;1Hu8v75<}U#BzY{=#W1(8Ui!~1E zE|9g#+mDmQ3=Xz{&3VEdU10U&!>s)@A573M-c#I1l}R78=F#?eACC;nK{5M zDg3+fQJ}A4Ip6nPpP_&ZyOi%neW^K(0?mE1(d8&42}o76r7H z==XHZ1syf8!d;;gG9%|Smbd4xX!sHq_q>T-=yI|Ot`cBaZt#GFT0kVFl|;KVxDho| zl+kfl+rLzb&QKJSQ52w=u(RDpf3m6s7N}SD2E|O>G|Q*}z0Kivf>1eI-p}QWC4iahxv{kS1syU7}8< z7|6+QYBq#T1=O-p9`d&z|2D?U6=F%;tY{7YSX+6;bQ};fr)3PRW}|R~Aw`Y5?`bZZ zWbxitzR|!fC0b)d7FEb0t}d){whR>V-;g_#MjwcWr3v(*UOgdfXX+?vKXx>8T&5n& z9wDSD%U&o7CV;}yx6%5qo7d`R*uEmR>&*DHw|7U*J;&RMT))g-Y>b5dm1igXswD0Sy_hqXaVdOUWJ7=lCfRfzI6J}E0c$caOz zTG?M1sysPgR2uuXVT2!wuLGZj^nJ6JKE^Soj`&eSd*Fh=h!Gwbioi^nRLDPcRIq_s zTwM*bZ?R*Rq{L&bm&(i7DC(dR8$Q4coD$LFfXT%l2H6la1Us`RQYs)IE3>A$zGi^A zOt|Nw`I+ks8HiS??JxdYs5Q98I6(HH9|wpGC`(ZP^nX-E+bt26-B6CP?{;#Ay(`j3cdmRYvmvUMz3umPY58RlRsCqO%G3l7Ej4PD(1O^kWtL-fuYQwV|+ zv3IZ;H@$yae2?!@0@8njU3yIV>xVTzFuO-V4zfbDPYX;}m)&d-2fp?8qz!{>hJSkT^SD&|%DB&6I^T%x)6| z4qMIrQPkqm9$`==CuF5t#&)^4Uhnc?%>F^xm``q)4GncBkqMyQOBEW?&h#8{+`WPr z61C%QERf^AZt5SJ8bsBVBd{BV>QxPL1&ryN>eMUZgPkC+;j`n+UCG#1Qqa8#A2zkn zd@5v@RKff!x1Ya~iYXlwwub6WNky{-2*>k_-hriDDKmJEW=5c#D#?!ph^$vlMgJTZ zAexLwzCkzt82*aS?#Q0E0NMHKS(w5#e1><+#NJgYpsNYrpc#sqcbS6XYw3az0`1HEvGrD#vn=$l^6k^4VmkdUZuIL6ViT0q4DzZqb~F$`T6 zr1~k0X9EpsIUB*{S!=4h4GM<49v++?fq0B@5ZRQ@c||WKrXe4+^EyzfA|9ubIN*M7 zeasrD`1%IsFtgKq4C)Vdb#}xLH6~Lh7IJ(^EilTb2EIIG&|=}<1vyEyhc(dg3Z52} zMuc@Fbr!(D89i!=yhvdY0*SGIt)NG53KIDC#Q2l+sy2G$F@A zowDOJz(w3NUof4b4fj99&`b@>eH}q8BCN?7zd%MgLR8pyiUA?w)1Zo)5{Cv(znmkm$|B>@9lYZd2mHu! z=&#u$SLm4|nb?>|32f<5V~AjHuLQ+ERa;-^i`&WGi2!#MMGn|E+~dOkNb#_v2*`L1 z5}c9E2GD@CsVbd*(YQI$iN2^uQ=pfEt8fGVT8j{Kk%VHXuwA)n`?4T$rHwqpKs^|F zxTWetz9=z;sEAGL=RQS7(${cv=f}e^ea4z|a>h#XLuD5b+z6R&57|a zhUy#n4~hvD%SaJUqfdaGy<+$}VsO+hJx8kJW~d&TLCVRfaxP=oGhAjm;RQzTb5lf$ zhOIHm4Le5$oI*_(H-<3Kp75jlz{K73`IO4?;Ue5|^ewm^U!GvIu=1KiOMT%m=rIRr zbpahtwRPRQji>ZN{F|Nl8N@9(OO{k4L7=uaJ0l+5+-_QJ3mJX}6c$EaDs^`6gAaDy zDP)--ta)LzA_H}f?&gCgDx^F4zG2B0?@s|}^z?TgrM0hcjm10AWH0<>##kgD1$kq> z|AMDFa)({Vs7}bOG6jh^xPsyy<;%Z*+MbASnq6MiG0h@aTnReU(+G(YR@T3 z?}ox@i1s%fba_jN9zw@ZKKsbFRJuXvVJAVY3q{2eZ!e6u*)v5~4K+sYCnV$(b1X=o zNzn4K$erPFsVyHM-Vf$nD}72N8U06$t)O?Lj!i{h;*eU<(el?-vywK|1PYdZTutvf z(Pf=+Qc3>mP`rNB{sg+eKJS+pQ8B+Fa9qtUm4DO#FAOH$oIh$lckLtauv^};HjCta zKlYOYIU10F!8dd^g+QTTq6)!~ji<&PxK-}p%1P{YKpgh=>my$-A#!rTCu=F?IDcJj z-{Rw3yf1Tp_(pyc_}bePxLGBMJo~mrd|AW*-Ma)uGcS_RQ*>YKo6v?FD_}9H;NE62 zW&;enilxsug3o+skAg*7e3G!{+|1aG{=e1;(m6x}99$N7#AdR#MwTx=%xByVOf_$` zOBE&L_HlzqDE`}5Hj^LHz{Y{^)B&~kIMTN|k^y;;Xan$pN^nH) z$4TP`8QB&pdXdkY(B4(_@TL}3I}cAh0%bzXvdgAGM(X12<|gQ!G1cZ~qI|pVaC+Z@ zIizlY?Zdps4zBw+6#?ksd)u!DFH!<3nA&XeVHV2f4G4V+^V*V%zhl=nXM~CyE*oRBIB( znfiD#b>s#*S<^wCI&nKz4r}d|(h<3`#CYdgrW>GP4#u8t^ceC@U5byuHN7(Ey}z5) z|28RBG5Mi8awdcXc1dJJf&BeSw`tZs?@1xXner|z6_lQ^sSG-0cX0HED8j^xgsPb_ zBgQZmB~Q%tMZL6kuC2JKEtU1&Eu9`7S~N#YPac=vR;wN)yS4Oi=_N7AMh2qApbQMA zFZDv(M*fuNJ0v0Ei@%k)lFmjFtl%AS=i*BugS4RY;}g4jUEv0nY&4;A#OdQ0jPopa z+{t5N!K!`aoOenT8+$U9ly>m$ZgR9aB}B<9X!~hAM+u3~WRCp&b9VKd&toS;JJi^W z$KVM-J4GYZ51}D9#eG6s($BdgfyU^a)co=mjN=4+Yto6N#YnHREVtSWx7vmKlg>eSV>+ zLylpw2nzW${wJ9WkjiAr;jgzx*H5R^t%#b}%(v4WmZwQRTazpijkA9!YcZr~^T8A9 z?wlR66W}5hL9PK3?B-kbd+R|XrJC%`(*Y#Fjh+r0_rKzCb~ z{?ffF_7D8h-6a=;cBx>4;$&QMTf(D+C4@!az_+6RehEZ6MgwfsqbwrP7-MT8_aBNqI}|JkTbv7ERs zY+y918PSb9)n7df!Qa7bYNBe&9?r>SQkCGAHE%ABxTMRbz9ho!jVQ+O=bg^&Gj7yVI^15lj!;{@tAxKiho^rs?Vs&TgC=G*NHJS zq;@)`iHD!AF@kA+DijXn3Y|@9qzjVDhzkI^=Qc(Sa%An=AYHv9lU=A7gV3EwNcns6 zSpE)Mb&A)E*k`^-Wch0#lNR8fxWUUC45!&eFErDTGOYckWc08=;juqALmP0DC!>(X zQ9ZeYkvk20Z~)CJPiR!-SJXw1;2colvS`nERk z6zBKBT0%wqmZ8_i|B6r}O|Kf>|B*?BruI{|A4|&Qz$2bmk-DrVc^=ma+xn{Jj>UM0~ znbrn}s>G{>$UfWg@=cVvh0aIjR!5MQ3$|fEzr4mnD$kh!g1@V{x^PzVVV|bpa^LHm zUhJ44pYtFu$Ut#zHs)hK`!r$3T2ijTj_kNfQhfG8rA@3?75$F;RL-JI4Zq`iIe1Q0 z=mQ1uXcRD%Nt!QIs1@0ey6W={SxDKHu6MMf%$$^Z(x`Y6GIKdiaSlOZHbm)Vj|Tuy zd%Aa4GjzK2cX}ijm<*u5gL>cScxI#?>m}+D^JTqdEVW2}+be%fE~KC7wHSSem|$My z%cp6LEIC{=Yb1Od9YeQRKV!KPI7csIiAk#+gfo+#qNIk~-6jh@7GH@S$wBJHesXUbAWcSf!2xKVuRGCgk{DtEk~L7nWX(0^ z1x@NFb`*LEN=)XmEVw;9{ls=KmCMiR=?9McWOXN6kq|?N-%o6or6K5eE@7u>>&LR2 zOsKjYNH(8yyo_iuo6Ix}k%X;fnH9J%wa3r|Oi_fnn$gllwk>aS%P={sqV(bkFS)1q zGWwN*sHlh+(eF4Q*%;Ft-!9Dr%8Tgjj--_Ons=T4gE?L`(c5jo6pn)R3|eB_XeMSp zNpowdmjFF)HIWNswwW5!_eIbxARyV)YtUBwV4HbFYU5akNo02h-XRBj0hii1+F`Ol z!#Pe)EwVjvm`EpvY#R<=t7s--$U+n-sNaohI}vuXTx4pEV5my8HJ2~mv{^8MWblq9Bom`=@_jV3?v04YuAwJ zjR+alt+5-N9ot;%f1JFN276s&=Lx1_xNxKS`9-$>uPBFHH$q?Dk)9#sw6FI!P?TZd=LCuGT6w&r3G zbk%N(xTnNRS1)S|eKiKfAQHU3lidQ6H)KnimjB_o-==;g=Q89TEGuVTLn?<_as{ZT zKbJOU+iwi@_lgN+gsZ3y4e39ke}wE4 zIvE5==@ZBOiPNSHzV{IP`9g>vs4>g<2Zf%tPDxdlx~`R>5wB7j91sOMPJ6rirMR7z zttqFX-GkvkDK$I8ZX`b7T;P4K9!>G8tg#svFzZvWIqH5nXVOWdcqrH@wdmc+k8{5k z%70Ag1MZ|kZJ`KVFdKXfD_99Vljr%WidSAv$wj~OPfMND%fT+LqY(%|FgmF>#n-&j ze2XYCI*^3-iErc-=>LOs(@2#|Drzpn?|AvI4SgWbv*2Jm!=>^Kc!?(cCQ~a#D~FLG z^eHEefLj)fPUY6`4K-dJ%#rt4IZsR%>Mz3i{n4-ZGd>O+V3RVDya8e24KH90ur4x; zcvZ3Ed1@OHvhnvbJ%<+sV35uALnu1Eo|t?-rsm&I3T*>LbSW305Gsw{U1)lx%h0_g zZA4Ung0dbAcG56)O0sI}3!e89x)wK)@W;&xT#C*HfX$PD1L?VtEz%G*W=v&7#78TK zk}A3LMF|IwKmx}vdEdCL;-X87yFh$8x3DC+-Db}M2p_Dea{BTJ1^Av0adVkoM__Q! zA)cm)ft+hwnFw}F+i{bbL;elDsjb*@eZsiO=M29`*UG2Ru+hJy$wvKe?7az8Q|Xp3 ze(P#Uc@?mVYEcM8uL`$rDT0h)NTeu1OCY6K4h*71nIS@$$xs$5Qb3}jG7~jQL>mXlOQ(tQbthM3N#Bh!u!( z#IkEirbElkC+Yet?h!#gEPAMJJmYJUg{|~lBFN+@={+5jcIhmbDdj?%@Lg@4xs?y_G=(r0~kfbGyl$r?{YZQ~T zX3@2Dr{9Ii&(m%=3_3$!tLS_4YQHW#_ho7YUR$J#Eh8SYjM!sWy^8J~3a0I<68BO| zbH6r@T0X6#8}l+5ZP^G)*;z%HL?;ALgA8;s>XA^pmaM_hw0g(Tn`ymMX^fe^?wgoz zdDVQ!?S&3Un=!(wxyv2y#?7Bx-9VA1;4F*u^X>~I2VwxLY7ih8TP!4a9o%C#JYKG6 zG=~b_D1F0(rzhn<@}h8EGACdvM`-_sE(yKNFjdHttH>Z0zji4(RW~ zp?H%_FVNmGV2T2IBfAbvw96e4>b6!9N>0xohRK3O=jg^CSC(-xjr-oKyg6_6w+~ff%fN>3@Jl|>7NxQ(px-XOeWphI zG7wfw&~*-R{Vb}N|qM+WZq;`<;HNgZ5-C?0a z9K6U;ke)zYCdyn#Fth2KD5wB~s6A`t@1mp7lGiid%2Sy<@2ryKeD8w*e3Fm?2^PT?nuzk%2)R5p@MT|&Ar>ot>i7ZRLv_LWK+)I7zKrL&TL;$Ao};PwEEFwksKJ0o3uS0h!eL?X73KZoCP4F6zVS1=0)!yAQIJ{TJ6x&ip%R_>sft| z5NUx`aPfFl;x_>7rvXy(?jjID?m3ol^W07VVg=w${^+n3N9zS-sTP2PSL@t*KI~9w zky<(Hasr{J(fE*0{kEA*Hs4q*48Ceq~|v;ZmT}zPSJWsF6m=m zIVJ0~s5a<^Cy`&aBv$!+pJEBZvR72 zH{k~DHPv&v$%V(l#?0R=kNu)4X4D^v-I`jkZ%fhUZzQYmoPFK_5#xvF?;xTglluH4 zRv7YRgKD^j`}B*GTL9x(@$J_U28o>6*d7zE?8h{VuRK&9nEmqhde};6(*0w?&abzO zg`b;(RtZ1$fWL{oLw~p(OX6?aV_pSfx#^qXqgob2V+()}i&hb;Sy&Fw8X1H#|03y6 znO2@64zo4+NN(H3`zts{cr5lAe6d(#&FM*N-#?{^D_Jk$qzP%w*GWIushM-`l9fSg z6V-IIwZ2|;mZm@Xj?f1aE>IF>!KR?#of@)mFOMu|j>%xcUT24%Luxqh7!AHw)*{4l z3zM(pT~-olIYq>IpH!Zv$6h#Y*)4??n?qoq$YR=OLH->yqCxf$1&0s9%t7>TdaQ7H zl|&hyx%&s&w{AISHE!8giro&Z{$?Nn=0a9miJS!AZ$1oC3{H@xkL&Sj8Z}|j*sx^E zcVa{bX4~teGd4U3ikQeUNpz9_Hhmj4mEi$z2}Ob0^&L$)WQ9Xro!OghN6I0d7kvNb z@UmY`4nA&T;V#cZ;iTC6;^O`)Dc-00;3Hv@T@Bu=4qz8SG12^$?Wl4}IGn!4P;{`V zOvg7!x=VSDF}-X;kSMdFZQr{Q(KYUqt|{B}Jxr)?6>(YT2QC}-%0tD$+fq|kw(=ae|FNeXhx!zuC3T7&fEK@ECA#Mi|QET z)+yu?6Il~Ctf-eD1>pJ#CpFhw<$j#3o$18?!38t}3aVsNzDJ+`0w{r5Wsocy7-69zv;H39kT)~oF2_72C$;g z;wE5S1Xt85BqOg1(v8!+eL`U$zjOQBHk8sM!?3PlJ`<0)XNRKh<*T0bEY6pAGhI*N!+6ieu8 zb^chTw*0|`geD%7#a$ zO#f_NP}FR1g2K()sPm;%9otDCd+}qBOd3>7cC0WiClH;QF$>cQ$&ZR+Ls)t%H5EGH z`d8@%=^#X{o=`e>FeX!BZ)1EzN(7*#VB9>>p}}3!W(JjYG=f_t1m!rB6T=o+){DUg z?=OgZ43<9*;!_Iz4ql485=GU-jr1q1ma3VGWAIhRn5C_gJMjX{u!?IAP+jD(T5Ww^ z@K5SsKV+D#fF|3Z%&(Bfl(mY>7|Fb|f|>XFJ1%tkY)GLL&ZtGeDWNZ70;GPL4%AH@ z#m{@t3xLJv5!`D&T{xr;G3p872^Jmd62pP#62MH9a0*AZFMT!WEHF&6l!GRLb%b!4 z9AcEJHN>a3m%Q9_K{#?S>6T-ML~WI?Hg#uexRX)u2Fz=C7$Y^ifm|Y5Dax_HlO$%#D{rTW* z(Xku{odeh_^J#ehl7AvLUx;XrX|(g5wExkAQjyb~!A}YG*S8o<$4)SAvxf@_W3ws6 z9z-rn!`fI1X6o@28&kaZR~x>tE&CX=+M4L#IhhPWosC125Q9sGv2< zcalDrGM8Hup(M-6I`ki4%3WkdJ;7o&FDhd8Yg(Oc9bjM@3BSdPQPhG?M#UVe?qo+gO56OrPBixHn@scK4-#Qa6 z98yrPm5dH4Bs~C?i9(&+q#yYg!EG&kmDRKy2J3UDE;TRuQ3%janr}I3&rlvkAz9Ph zpa+XE5yZs_Q>*r63}M2o98oOcnjZ{#Hk8b`URZ;VA1fp_7nKF`j?}Ao=aTJQ>g{34 z5WqE)K33U2#%mvWv_}#(#&A;qLpbeRg@R)!^440q_zEHKqO@XzeV7TqSzFDgmzHTU z@;Ls5a7;Np<7w-3uyGMa|4=>G&?4*V1}+IA!kUPoVD5I42BZ)_wgO*+y{m^A49f)S z;?#M?CrLS`Etp=0JZ-i7@PzYm|61@UP4ejyFZyCH{5*}O>3JyOzm&)< z>u29%3KKTJ}UUiBK?{=gsVBFkfVZV$}CcK6bHR3 z7vM;`u}=y5ji((HbqxE`=(u{+bJz3KMRw~avfhe#A`L%;%{)S#NIopA!adqYR9uk(657Eiy092$}310N3QSSXeEaKGJBMSiO_t%u=N5x z|4-G+Z_VD`@yvUj+m{dooi42Q(p;%`Tz*hnfh;t=LYd3)UyY7m-4B_4DhP4@UBKx! z;>EkfWi#4ZhB9W(I?2#F{P8}Xp{3^ME-N-eoSbRSb<@D}ib7+b!VgFdR7Qfv(8H6` zUCuky<_SEGlDJBlJJ$O^XaP_UJ`aNbT8{^1h`B{B(8<~0Yp5^~BrSkg1bwhm zx)g{W!^%^;yN-HkR1s&6L2(D!%~7yKshEMCG$9lVa|G$)OUh=LDr;1@sBjX9izZO= zo#g_@0g~caG0a%?+%Ux#D+udsWt<>%dO%%m}gu+5Y!Tmy0{7@+j z|R?-cak^X-IUk4Tl*Xidcj7{2?RGD;GFo5oZlshfR z;<6g2Hy$5^B!-I&AFP7T(cI0rXq$)H;re^NZ@uWaI zfEBVx%8b`tZ69h4d;0YOD#*^tQr@azH0t?=FFWswnfjLBC}l396+mSt0T>B~J;f<= z2MjMUvNl)m;I`L-qa0|DS70?a@kWEisX~S@as|Pe@2AppLEwlaamSq1%%egZ{O#lV z@?j4*x;@N@=M4!}o}33MkSeJ~+1v(APW;a!cmJ6SKtLFf**Dd$AYp#tao$oixn2Ob z@D1O=uzYSjR4_0C%PdwfipJV+gsIr_;++Gb5tW3C0A_s@XUDx%w(@s}F!o=ev z^1AYU_d&pyo|tic>Y5wE6F5U!qi+RB*1BT|(op{#-%yew?nV58Bt-Z*x2OoEis7z< zbOO;q&~#tzmtxsm$_dOW@h8ofr*Bk+l>BP=4i(h)KAe-x7*CrXA}%yXR*N7Rs99c7 z$8z~TYRoD*FP@p^#*s;9T}9G1kcg^SA~j%et54Yg;EKsTx4>(Nec!Z3ae*a|mx-AG z)=9FL42ea?@EP7a0&sBNuo>7QuOGn0+jbnL2JyCS;r1C`Q&%KT)Uqdz|SC- zE({J9v6VM*Z~fGOi3i`1b`h{Yo*otRPBi<~1Jp9s_F}!QO$x~ZGYV(=t|`8oqjEwa z1aAOXAl>_OF+d?2a{-Z3z3BND4Q^7=v|SPLIB;9*q7*^_Y~0NmyqyNAPGv%|gwwT{ zG758y81^243|^p4@wSmop-HDWFcQ6rCeA34A}KKX5BidaI!5yGoHV_-?7>+lFz4pL zY*J(pcj7ll@^(Ed0N`={mIL%FP2g48M;uRh1{X?;C`?YeeYU2fPX`j(wmjSS>+}f& z6X!EH#XW0>(Yv}OsOjU(gaAG=lU zyuJ0Ny>8Ph%_!j1!uCHJT<0#`fR}WN{fb8aOj;cIZo4)g(ZSR=D`SJ$ z%xb?2HN{Tv*0T*=)^`{)W+P(~wq(_z$Y-^wjVKFWP*V|#1GMO?jD)3c*Ao}zx{N0w zBPs8O4pmD-}0^rUG*L9hGq}jNXI+UQJPTHpbzz}&z6AKAkm;J z4nBX@P#|A)a`3WOnw*Nc@XE_!84uSLrTLL&wQ9!4{UU+`-T*HmUAPgC^jh z5ty~xJ|;3eZF(|?j@lQkSJ-Uac%C(R?tK(kP5FzaUIDbkv-^fWj;-JC$&J?y8O@}QdFGGlf>=Pb2L;d4c{3pO#0 zdanu_X@Hfju;pcQrp1CmV1}CAnS29THH$Uo$cXt0VH9wnT{a;l2mui}R>cXHZr6?} zLA|01uowlx$D`860B0CLstOe0z%Yuj#MyeGS3Lc-&}8bE@08IWjj26VZS^}_-zBJ< zaFkI(3y$8>o>DmB2dtgOD4Zqg7%X};4QY+e)DBq*TQvw6E}dRzYiLKYViCKbni_DC z+O^jM9=n$R>n2pyK&~yzhmtpmUyU{0N=gFrZ>9mbN);lmBBap4Wtrg#tr}kx;LP27 zcbTs_P%?6;!f_2;L>DgaXYzJti)=j3J4CWxn&@H?L68Z>&-Q3)#+Q)ttHfKpU0i?G z4G)3_=7KAkqWoFqrl^#@#i5Vg|2xOf_}Z3Np@SVg20~B(-yFi+Q1(w0{aVIe@AK?w zwN1JsQwY-87+tkiGpoQ?Jms&HB( znCS#Wc#9(RUk|K;GN`nN775!-jDi5xzj_l+I@Gxz&V%c&PO;6@olbQsdIw&Eq9uGXXUS35G|5$ zK>}6kQf5fCMBtg0xVicZBzm%Aut7@*ksh$D?id4%!GX?&K%{rrvc*Na@oad}4ySsp zU-IRaG2$R#ywX+{5Uq8`_VsLPUdb>(@U$Ua;Dk1XK`IAE$E-vGPS4V|rfWmL+CyW4 z7Dlw*(DwD7wU*_QUSOeXlay;|ye?PqI-|nimjd_#M&m4bR}GB2{7r&yf;WswJ2I+J z+JUIwG_J~M0gTYCNp`?ey?;F5ZR8tcqJvcezzwcYUo>onRcXEhM1XQO7YdYTBt&%Z z-C>Bdne?`HyKaijv?uUiV}{nNHO^Qeq~8I1NwR3v#z84V+2L;3>|$Uvxq_PHB@3-T z$e1vraGP%mTXFO9@h11l<=3! zRrTg*2<|sz1ofTvT;UIUBf*73FF|hkuKx_zxqdZ_?<)l&wyCZFxX%k{%m(r(X zOFRV7=}i-9N@b2P;k|1=)H%p+ z*q)YwN>F=F?yBCh1o)O@z+~x_?3}Qv6q95bLj!EjF}H@k)Eb3>F|>4qVvde@ZGC0E zR-;8joAx_MtS&D6D7mIEn5Mm{)z>$p%{5MM`bUlEpEw3fKqT!3*19nKJH{ixbOM;h z8@|K9U&CCNw*C*Hv~xoXj#mog!c%W-_)pYHv4UkCl(5S>6C9Nwwuf|0#g$9@k6~&C z-Z)W<76&>sr@k*>zK;RIzNY#Oyd*boOcgAElS6;27+PDXw`-jWXj1qU`g=U5lDC@}UM*%7Yb*7d>M0ji5AbQ2m*lN1D!Gip{jQcC z=B!i{zJ^3vt`tcjfJ>fblVklP0r~>C zr~%0X+Bco>t}b~!Kot~^%B-KHmDt+dj0K__fCgzAz7s-1H~{&hRFhpyIYEm_p+c`N z9P0zw-L$}Z3r_wY6sGD1Bxk*Jy$eKL0Qyc1NmK(D7m}^}s0cvo0}To_a@wE@ar_^p zD!jB>1fJU}_^#A%Y|?cfWfJ?Fm?OkTFlb+5Gv6#)&)C!197_}9098$U&H*>48uwO_ zD;Rp8h_FL)h$e2S>~iK|z~e~1k?de;6}fD{OQBQ=N0chQpDF4}Go%$pkMJy+5+nQ~ zOkAW29%GDlSBD2mX*(h;6ws|tH1SW^-`wsrC?|>&D6RNNyv--wq4_qb zCd13lF_tv(GsQNe{UJqG@h;N_SS|g=%rq$`Lj3hWD_81P(n8JIjf0Q@cq=3&!P}7*_{%`Zyr&Iop_xa>6SS3YoLOQQB@dSCG8-#+W*^O*Sj zJp2dD1>2p>ZDSj^`z}AFg`mU;-p}<2Zn?sGj-bDq0pS#sdGp)_Xm&kCqYK9=Mkyf! zs=l-(!0+kuqRo4uQUr&_BVC#*D4B{Jy6_v4N0QA%pO67Y`P7kd(a2;V_M^_Icb47zb8nJ6EA!h7NI z@>=IJNvwEHN8iqNipl)dfr9o;3`Vyzr~rP`G_pmuWDw;5=J!&~HmR>=-Y|956q%6B z^3Jkn+u7XItN4p)Yz^OKJf!_aThH^T;MYR>-V(^G#0QAM@gqdCc6i)LOk0&WN)iBfl@%8p3@I6R9ut#Y}!$@*521-X_9d5>_4}o zwa+D7bX@qVN?e#YV&}MLW!>2KHg53iphbJZ>!>*Q$#u)&^|_aOI);&BG3?o_4s8y* zS6liodfcq#G*8trc4qv+S^A$-AdYi__&Z*y3&WhIUfD_`Y=_y|mcR3M)^QnbFQE_A znSukB7X=g|kV!zeRjr_(xJHUr4o(!nv(kcBGa7>9%5vS5NxXjFN!TKM=`ne`G)L{s zIz>=Epy)&C-@vG?YxTp^58mlJQaL)=Q*{QCxsi@>c`_23GCxV8tflMZAPZA8U-cL& zkPfO1kw9)V=d(tWi|tM4SvNaZx)MzmE=VH4i_Dy}x75hNM(Jp!3IK6rs?5vusf@>` ziL>a&Kt*T(CE`KD%$Rh#<=s=`1vRZ5>lXexI5KwJ99G2!NaE-^ItgCV3)Eo`#c5ap zz8+q@86b+W;YPygZh>**h4+gJx#c$yJ|@&CzlhY2dDWQI^TGjk0-T-GSrjFS(FG2o zUDS`QLfDx1I*hAG-`MDadLz77Jg7dZeDN59CSFYL^+U22faj~}vWO}but zH~2@L*08RIu(5ClyH7DAb+vWo*${R;&lcGdC8==<>lsP_vn-J6+CK|li zDoGTZfSqil`BCbXcrR?q6RbB?KNXtcbra9q*v@umNsr|usZX4^HO2dtpOnNh)4?b~ zt7DU)@J``oxb9z&oGvU#bvfK>+n;qyPgRw1c*#i!oy7*~z9gfw6f$@jMD3K(& zKOu4z$VEY)J&V&|_0ZwU?PUUINjh2oE7-&-)JN4d(rNiBWy#GHKsNL^lNrf_7vhS_ zP6vq!Z~6CO7(N?%uT6iw$6m=+x#8L?6h5P3nBdhPFcF17!&YnrB7QhH4=ZB?JxohG z+UpI#n%A+?0Ni;|qZSKpbuDqe&oT4ouj8MG01LAsQKPKFsRv=W1%TC;4u&ZxQwsVS z74I2-syufy`(`ikKd#;8m)GEVV3R{qzUoW?ZVAey?6RutF6!l9jrdhLi5Ws#*f|S)%PTo zM01Q!CETW72&}c8z+;0(3hbs7Gko!D3XV0CY75tAr5D~pQ{T?OB<5o&$_K#v3i9sl zZTJWW+*DQDF_DH;nIw8gvR;igQtlBCuEL#^SKiDiWT~mU&pIxbyU(B0ahWYK@Hiir z!Rza;%E(N3wi8N)RA3(Q`dwZ;w3zj!CE{g+G}+@!sFD0#B38*UxnsZ* z=J)oi)8oLH$r9<5S1%SV&$`x>r|GYP7`IsOt(^opUV2Bpcnqf^1=YNAQHpu7Z<9{6 zh8ME9^CA$WqoR8b7S`qGGJKO9uB@+J#t}FzCYrJ*33(|nG8Old>;Re_rnRr9;KjeR zAJS(pWNJID@QMy90+uo`!B?p{s+Ya3JJw51n{^HW3nk%y>!LDT6>hHAIu3|o@R}s* zajf!iMXq{B53;UinrYr4YsL~-i_VJa25>?U^OYVxoALZ|c{szpT8=}7O`_Yqm0AV~H=pU#gF6a_$k z=}lE{Z>7v~Ca(sXu8P}VuY7l8p&#_>Fg9j&2dvkFBP~RiRORLun55&{0T=qbx6GO2 z$HA{G^iFBWTsTG|5mLDic8}d$A|GvC>*@Dj2<3kMD1Z_1^${kFqzr zzX4aBVXw}2M*o=GZk=GNK7moiZB^U|v<4rP7XfjG%Z0LsUS?ul_?m#o;4LWWAgnd4 zrmLfMqD-x_mKOmeFzrZgx?TRDy)zII>rSi|!cfv)WuKXW;s#kRq0a&yln^~iK6v<2 z5NG+6M!gfG#TiZ53*8Dm7mQ2hwJ-!NN?I9=4b92GwEL(OA)<9KHm65F>QEIj=^0Lw z1r6bS7UthoGinQ=M8fB(g_&Ey==y8Y*8A5Ly#Vk1QZE;Rj7cg<57}GEkcW1qA@@>b z;xg+`TP0$OXvUQJ5Nfpz`jv+sma6ou3)oWVEAHAH>uacn4G~-Ir<0Qg24q8HLCi2O zba+}07uhA#QE2)Nr8cwhnAR;E`tb|K0e#K+5 z#QCviOFp>RlZw*Cy!g7Z%QQPWcoa^-)yNLUkLk6LV&H6=JzRCg1vzgfPUt%_HC$H= zTj`w;qG?q3G>*eNpGqD$K&^NV_~i3l=chgC*}?O0?>^fFYKdOF!Ep;{{QIjMH9hN) z0k;Dk4Mj!nJ*WhN77w5g2=W;KRuZFwrat)qAQdQHHmo3-xY{V!ZqqnT9Yv^uv3E)ttLYL%a4)#Zb5+5wv< zga8^&3`m;Sku6=3hNeNd`l#1_=#M#uk6QuHD{_tGMd%O)atU@vHLxC-z7={;e9wtA z=XsfmU>cE zWILzHD!E^Mf=&NX|8>PX>-H(i?pib5_`^2SZvYOIbmA>vpDf2+MzP}nU zCfjr&%K)*(g!$uvZ%KMLZ-9~jHkDg*u9y&6pN@JA{ATeY=s4!>$(h7#c&We^9wjl=`Z#BB}n$AbAKJB8=dcK?p z{L39M246d9zUurvwofM7V(6q{@brb6aE6zE(DHyPQ~l?q#XqS6bev`znZGI$Jp62g?FWYKxh@;TF$;}3p zCM>QtSsbH;w3e`d#E#~kG#OeXVinn^#Nt>ih__L5X?a^A81I%7$H<@MW+7q%z%hW09C zv-ce6KP?(N5*sVhiqSRo61WZa^nBaCCAXF zC0fs=0LI|;*A^QV`rB0GJ8-&(0T@Gq`UG0#SqWMV!p#dBeOe>oEp4yv=acBSddbuWp(jx=X%x+VY%NltOjPF|7Mu|r zr6N-krUK|&$q6bF)vE21M-kFDrchEm9I@=`b*VHoo0L`; z5}w0FYrCZ3c*M;j>>55!Sr@V{mAW`ggidugq4dhMT^4I-0J2s!Z!#y1qDO0`QaSa{ z%EVcY*g~PUOD9b+&a6-I$?4+?yJQrQN|iWDnRB`(ELt6f%9vrr$-x^9m5<@*d3Z&{ zqdn$E;7RU_cx9(K%TZYYSt&O3l04LN9(2Z9#$)c}^rIDwvraC7tT|o``U9DFH`gDq zyuA=K4jf^(q6~O77U&v?2`amz?_7j#b9`?+p@Wf_HGH84_q^Ru;pZY+eyKK9?_NoZ zK_Atis`|L#d(%Ht8z%bN()Uo4tNgYY_B`}hIA#o`w)nDC@Xj)?^Sqyh<+vakTo3dW zPoQtO7iJeS`P5J;BBaQhZso|UFuwe}MaoBxOjVqOr+g&(I_D_fT+MhFtgeC#y!o;W z%$7?b&cYQM0FqsBo;=~?et^UutEuR(Et_#1h_j$awnUX&ZDbxIl=yaxceR<1*=86c zeTB2_Ck!lJt6Z`}bn<_pQ^V=`GP7t?mzbdC0HRb3LoEQo!sAh=xr}r~>6Nw$fq(3a zdQ5+T2mCn4gSzr&T=PJhNjta(M4VjRNXe%aKD>Z%$O1BWiPH`|an z052(9uAY~j)%FX<7kn1uKZ7<_aDz_zf9k@|hqI<%S34D^)%@lA-M0?!-F;}2aaPou zybG4g22taNn-un)cAF4e|9Z2?)y@twICv>*^P#p~n>YS>&+e;dAKp9dyBMBk=dGt= z&6QZEmew_fl-7rohH$?XjXX;gH2fmqvs#eM0O3#f(Ng~>XqzVg3VFUhIO3yD;lP;# zwgr`{*oOHKXoQtJg=d~|XCD}P<~wk&MecJfx1CxbYAap)<#;wXf}*WP_XXIgWXB#| z>Pn~o^1-9Jd*&HYwp?X~c^QWJbdn?+KB%o$y&WM+#oqbbxz!2Oy;a7-di&@X$H0-k zfwj!gR`GhZ7w>kc94VczPuDWv-0$vvH;Xus#rS#Z5=E0~^rBFqw&l9^J5Q6m>|wS~ z77TEI#dpeTqrU@EX%06A(MH1OmT zvj{#F&n9mEH6;KInQcJ4&B+szsh!T{z1U}DSov-4la;s^vQIsg{6612a}zR(45=a(`5q=O27cmQJWs2n-f-@{n6*7-5z(^=X3X*c zw14PeZJ9+jud|^50zxP&JiOWbcE3u~don+z^^Hp@i z6p%Q*tOUW0@jOnMkIxqIm4KfD0lr`R^kNobfDEg>H#rkDPwbXeo$h%D`B=-(i}(pu z#`0hE@c^&Yi2B2!v4gW`ipBZ$p)X8F9-WH|e&~#!E7{fCz4j^ByM2c;&x5+aS2j3H z2T!#__eWR~?n7oeMeX6mr>M^IwX;leasde|_DMY?q)$sxe1`2~VRfl#U`3^4c{)_c zIB1WXhg16=l?5thxU8a+*UMl4ZsT5@v+4B98FbiI#K02(Wr3Xz2P5i=ZdeV>?6@zR zMPWs?Pq6r~{O5>8a!hAvzXP>qX7z*Y;c>(~BCBr1c}B@(a92O(@nGtrTe?wrFy=!x zbUxGv=S>1Os1*4r4{&@<8H{`a*g#w`&qxHvVJ5NvDX=Ljfqr6mm_*If!S>?nUq@=`&vflcq+oR0~H$tYD9xdR)nNK}UZ z-0f#2|1XAABqsgGf93-CJiI3S69b;>s6Xzl%f9;q$9N$J!oQ#4aUYjBnpV@=haoPAFcZ09`OFswhBxG$bs+xi z`+DfibLue)_YiGIWW^ki=^c6dh=~o8iw^VZeR!I8RG7cP>5Pz!T268x;~TK@*odI5 zDK_CBq12kE_r&J@Ikq2%KUfr}`<^W?Hhz9Oewc3Z{Ur0_N3yRdzP!}1EDk&n)#-f90mz9wf1w3P8p#Ag@$IoL`GL9ye_Z97*Izv@zz9f*M zG1ZLzq$!?A{r-h~i1nI-J8tvlhTy=5bWCUHZGn)^3rrbXUh5FvsDzZ*i~0}2%G(_d ztkpm@O1V%$;NU(=bX$qbn05hd-#2K^UPIs2pCE_4kGqs}aR2C_RA7vTO(<>vP4AVq z9OL_GUsG|NXXMCjFohArNy7a3T!4$QI8G{O#kn5n97{ObMge#a*- zKGJ_eg?ZX8@X@nmL`52QwuWA13Y+pjcp$d_J~y_f`BY)&Z5^;Mbj}Ub8WR`f7HG^b z(~H69)1AX>p^9*Zxxv6AyIN)&p|vhn7~vftN&ZuO%h7Wn;{MvN_y#2EV|dBkeCO}V zKIOOy2jTo_0Or8_7+%DGf^3wX*w7F<=lj!`LEyLdlwrCR8}6%$O03RC`N9$NEVQ`R z6gAg9^B9_ilJy|G@L`__>Nuq>(U$3L$nqE2!t7z_NN4C-oA9u18I#azH^3V9g`*gi z-#-8LAlU~dA1B~8zBH})E&(2z#W>{3XPoH@Z{^wJh&W($sHg&pT0+&ROIh1fOxkuF zK%}_12JU+m%1 zCLLwvT_}f?9x1Ui)!%Q#e{5$+(%+t4`x8kCA2{-@YEG^Cr1U@18FtP-xBF}Z;&OA5 z9go@^nWFS3_)f>XP%)_~1tiRLbr=zPcEEGW(LGS+L*z~;g;@{^?_1SA&F}2))ek6u zA2<*Zaoz}l_njtLojIV)iolEW^#cR!_s8w_D?hyAApMbVRR&kQpHSA!_hTF6%zK%n zO@0MiDDtF}PikKW_g?lIK1IULPauf09-r>yaRm6ZqJU74ly(@Q`WQM-FFKFud(@WR z>02Y(Q;Ny5g01ba_I4`PkFlZsVssDtG2Pcu=aDGJlzac~6XJY->wG@3bK(q9{7a50 z3{mE_)`;!soBci;PbbQ46C0=KGo@=NA-`w=RdI?ClY%a*JUJrFy?Mvly`fc>>##yD z@fjvYjqn09&Mp%o;%&ywL!PLHIx*^dH)m*&A7>>ps`c|rYeoIgY9?7_gWq8U$>kT~zV4sa zzx)hi_7tuN16kP!B^1~_+LsjdPn8C0ChM*^#JI8pR4Z+?!QDAi?&CfS30SK#{E3x zkT{;}70kpCBr7P;W}(XGwYp z@$GJ-GCgeT;Ev)l+WiVS>!^tQbtoEm{AGtfK^baK8e}&gv(mU|i z0s=HBaslNcdVVrxH~1v^J0Iq%g2O~v z%{Yw?Dqa7kag@k%d4E2iG8Rg#64m-f`yY!?bLm2N`j;h$mskx^?z`7GwlI2u1^#L# zFeHT*29|yBQe@@Bj^6dfo5)TDksTLF&*p3BJNR(>ipQTIwe*6QdE}G2-1~m;edV+= z%)qrZB{y&mG}$mI)ZhD)SK#q=LEKIWwQuR4c-v@SyAVFc>?;QvF?tErpw+)PrYBWA z76gFKe4K}nF#{qQk45C*lxm+jmurH5LQ{@W@72glNSJ|T?JHQRo{|uM66{7-E-Unp z-Ysa&Jsp(GeX{jLZzYVP{(G^TgNMlZC!or+erUuSxl$-Qqm|}PYhsN5vFE%Z@wt8; zF%V~+tZ7SrV&d36YE6M+vGJHLkze7P{mXY0mQr( zXpDIon$;h;N?S0mVYdIKgIVD1$GkT&=nY*U?WXBW4)dHv7qi@-t756wMn+ahW-8xw zSy39KfSxzcO~KOgX+AVU?Ze$PM4!J)Nzi16J~zVR2ghL88vL%qMcRncH?6U;#vkos zVd1hfF53tJOWdFI*N+aEr(`R6SbS?urDMm_hhXR;YHPQ@JnluzY`nA8exrebqLCZ_ zR9@b&K#q@ta_<)A)}m~mx^6X&DwrbegZi4AE;6=*d#l#O;<^g|hQ_Ggf?p0iA9xYA zus9dBG`AQwH#-}?IKL1X6~PaULJC5o!os2>!o$L%B11zXGDxMNTOL-K*aDG19+OeJ z*xqO_^jrd|3YQVbuYsNla_ZVBHUHq2FZ@>TNm>`==Lf&inP>_IJ2= z+uy$Z%am?*_8#5qmfujYux|y6+rZb`W=)Ln{+Yh#m_s8 zz+kZ6^{R)AP-x=gzwxrwn{Ti}H2+mZZ0-r4Z4RwK?*PV=T2D zRFO8-SnGVVF<`voZS3JW(viOtLK@9)8`bua9r5|;AUoRin3R)m$T3;9Rp%Q(oey1M zCcJPf`|PsZIDkJJ>UGB{_gMk0;_2L-7Vrh`b*dt^WsnYOnCBl3!A;VI-czdVQlB! z)RR77dH5jOt8UyVHSX-BCS+xA<$UCDD7?PnR0*dlQBXBnKl-sggkGY4okv=U*$qxV(u{rPH?7aHs^@c-tO{XqKqMfq{ zgzGC+Ct>p=|3+PFt6y;4Y-4M8qq9^R8u^!5`*&C$p9QK%L`3&J-RmpQ-Q73Uft_C> zIagbn^udtW=?ngrri0QnUD)exeIp8;F5vU?IQ<7N-^U&zSOJcg&Jo;U6I6a$)e`K2 z>D2$n+It5znQwo$SO8U1f(YltE?iRqJngcN(nu5k|5GlO4hP;h=_nl z7Z5@TLLgBop$Cv2NazWM5<*Dc$KCzi^}h4onRn*i8D@O`FfcjKIp^~^pL4$FtNQ@Q zp5eU>PwX$zfU)tgqeV7nk~gw~lR>7`Cg>T4vppnu(%3pix82DB8%wAu#cwZ&jcU1g zLSqq*#{1`)i+q~_>V?&~yhC{1ytTvGQRh5TDR>Pf20Xp2Viz@;?o*hk`PNC9>w4Hy zc~g5M*gan!;y!ohAb9?qhwlB6Xp0ZU2oGirdFB%bPD6h-!&V&^&CZ4|L#&4f_Ot&d z2E4xS<8d6FPUoB$?5ESy(rly~&gu^YF3MFc4p)V)dxX-$7h|!C%i*z_ksz zEvZxINSa#hUAAjZn%J=oYDj7;!OcpsuiIRlCfnntOrN4V$0ddgXuy(Quyd^2y9gb( zI!bgzhsZ*b7POGnU&pzJX;QawKP@7z`s?dd>_P&B{5{25_Yydst)4fPF_)JBnbXd_ zjW~Kqj+R;incG|P(gdAK-6v_tBJ#$4cH;saO7;s?_e} zxf|k0e`Qw*vTKH4Vemph#%I}77z2IgZKk!vUbIeZ<@}3RTPxLXDL}E(AD$48vF1A6 zabP>|qoVp94f@I{vQ~?V9sW6(W?v}Rsq6O$lI{$VDhob631=r3IlB+~&CLcLmhlQ9 zb#`{*iA17PP|z<2_WWL*@?Sy|@bQn|jsm}QueFWMWVU8SWu@I%uNpVspf-U2?SqYH zjluJQgJAL`Tm!liyFP@?x|n9gyL6qe>RYFN`vx4Ikqx%nlN0!T` z+tisMUxwoIMxDL=76jtr;sFxk;xT1qkg5NLWghPSRmjxT)aM209JgYP<@gkuP@&?XVYc2e|pu zKE7?*Tb*+cBso2@ZuysyU)phW_8TWO&_CFyk>_fb+z>BTv~$pXV3&c_DJm-uX45Sw z11RnX_9e2k;I5;icl&tfH7PJ|$;{@&!~>z@j{ogX>x=VnINZexAu1=gD4d!m>eYZI z$5Tfzn?-s@;|-P}2f%ek63Xk_yi3mO-u}I}Gl@VL70vN zMI<2EaL=MAW&Jt3FdFp4OXRR_%0`0mT&c0Pe|5!Wj#V1;=N)aDd2m3qgJ3n=&B^%^ zaJMdJC|XuAI+yJlhoK*MK?683047D?ZfYR#a6*Ep@D&Ha6Y`<+UQh-lM&}S&46< zQs9BNkC+?;Es*atXlzTKDTf%-q=AN&?t+pdE-_dN*>C|Lukp?aigxwrH{8-NM(Q*S zX*j?a7<8%>cUE7v=WN&o8&IFQIoXB&BtzEeZ?*63C2dyjglf5H-`nOpm?Lp63~QZR}&GiLmf4BI}a~ z+r#v~BSwE^)CZSeRpuP42&{-%O88K9lyI^L4n+LktLoLMwXWNOy$Mv z_PHeVUx#g46f4~;y+E@m-W+}Cx%6KG!1FXbC1v@k_DL#JYA7&>96d!JZhF&>Y7@*?1 zD3JA|-dF3bLrdi} zJEBqDBERdz&1xHDrbp{Mo|tNR@fN9;Ib^GBr}V9-a!RAH0MdWmVAEEHdby$h^Xf#8 zPB&z}aBgl+cRro1q8+9YX~NyyWfK#P-~Idj|BVxvC7!oIAZ8Zaz@8El(^|IcGz6E+ zE$w2kezhBY6&Wh#I7pT1#ydRpp}UEp&ovL;Gy)gWXQYror&M+k=`mdOv9b$myNGPl zQM*J70kj9%m9FG$bUS5ZqM(2jacAb@&$f8~8QpD}8>K_!7m=oFE^UAohlD&Z*?Ms=z0-gLGDs*H4M^%%aOBJDOK{j}o=_}zU|l7%?c5LQt@EglJ~QfK;Ng;&KT z>R*Swg2g2yT=zo!4^qMLYjC0VcGIl#Y<0iNs(L5#8bWof%8MfI^Hh(v-C>3?`ctLV z1>Iag=JZ*En8_fkFYoecH`yGH`KUXqokX#XZ_Kl9uC7vOhhJ4jxQTOJQg8`(a6`S{ zbAZ#C-lHNH8J1vbQbd006?8vbx&6Kvbgl2bxj4BLpUBQjwUuz|!qMmT+p^5bL(a0d zwSEHZ$)S1;`F+9XdFriSH^#0yM7A5yXur1KwD})6y;`{SeiwK56Q1Ahbd79;+k~OF zv;vugMXok^l=G3EHk`DHO!G~SK?}_wWos?CQrWJyWELE^4QR9gLc}?G4jb84=bISP zoY$k46kK7g*WQ)9h8#*a*F+AHr&c?C_s*D5MFv=qjxu>+P3hBAXO)$<%gT4#;BoAv z*hY%&n$P=k5HJ~K0wWiii%+@($G@aCbGmvV@K5)ZIp^F5YgXlLK4h{tjT6>j;KL74nEr1H+VSYwjTyX?T{f-Y@VclYQCxa`*DI_PO)7hu#JX-ApAg#w zxS*w7&c^jvJRlsB)Goo~h`3^5xaV2JbpI4#a4Oxguo7|!poC5hFEwj%`t-s42ft^? zkBj}HZkFQNH9cv&KOAE2Q6myR?dJ+5^{Pcf(nteTZMNg-jj}`T?>-kj@xQ)3-rrF( z7t=eT-8Xet7v^t832|QmZ)P0~v_OjGTw_#GHYFamE3 ztG$RVlYke33LvZMfk*HA%C%jGp)2C@`$F0xE*gn}5)K<*l|l9%?Lb-gwb|feaaFrp zuilgpq6!DO$Yz_rnkjdcTSUmBU4pe_NWJgRF=*QDmk~4Rz3(oeU13@=o)U&~eN&{= z68wT9;XzNX#gfn5hgyRPRu{oJ1PM~BN%^=SqM@M?o!h_GIXo;ao%Yqx0%_vn5{J#D zcMc3lNlT~F^sX9Jn07TMIh0|OoKU+-5WcX@WB;d4gbFw&{}223IktG~&!a5{%}gB2aF#vtj?dM6)-E!Cr7)ZfKNlLd;2c&Wkf;7%jIp$HN8;D@*+Z#;^%U6j`h_zAsbjm#jPFCjmP~+CV4PX2$Z~EIUy}!Ueqw(IJE7Z5bWko5f=gs0 z6a3OUi25CQaQE)ZGBj4Xc>&=Tg6gTyY^%)_Br6(ks?5zZ&F6#Mg^vHe*Tr*QtVqrv zOBtGKQ#(n@?C*T2Dn}B;W3j;7!8Xz0U6ZhtyXB(iiVtZuzS_%Ij#s613rx_}%MLG; zqz|;*Zqr$EMnTQ1h%e(Bs-Qf70! zr0nbD!GNCUc#?e`CBf43-@@x(6h1cMBM<$d7Yw7x-jTglcjezg)#}X-9=hftw^@1o zJ%bt86ty{uuyl5wxzn{8o`wl-4_g8Rs+z}}-Y8bdjVXfnRj@KnK@P~MUR%CxwpOdI zu=rcu2O6&HUylVWt=Za63HJ5rzbihK8{F2l;b*V{%nP~Z#j2Ok6Jv{lCr<4-wPVd6 zebW7EqrO=lyzgwLb$iw!w&Q+NPw338h_ZA2juJ)mS0%x1Ssg0Y^$(dgcx)Q7vTDqIth8$lQvQ@EYoeKOXQyKs}E8C_Z3a&DyP z$>=`@!17OJLMJm2B$|WI(=^njn8fvHJiR}G6VpRmdqtvmXX8(5WPzDiZhq4`q;(-) z0z`_3qMh!stSTHyRc}w4H|>+<)TLsT`WO?aYiqK98}^#`He1mm@kN7qLxi)JiwCoL zl*4HesV60*5o5!Y`=|qbdq0r=gBszuwu3j=y^wO}-wTXNg>hz2Uvzdsx>$G%OV26L z($cDHa5;J&6VMU}aHV1_IrI#a)nc=NbTqX{r4Q^->|)v^KsT0G5A6< zL|HSxPdeQgDTOOG14@S?(x1$*rhVmzj#ieh+&gC+zAgXWE#goXOC*`+L*2TEjDweanh&=X#^+WOW(U&{#a<<^^GS#fE*&o~R^ zPz^0ijA!iYbuhEuXdYs+zNNM!t|k72(ZJ)g-Wp=^#F53}cgG&et;M%{Wa0C3s<)k3 z;-2(m9hRFDB|h^}7!}X&U}E{qv#{ZppwK%7dI!8VTE-s+o>F?0e%x#dIAQJ(u3!InaG5HFaq60ge=; z^k(Ad`m;vp26o&kn(#;a#(Oula7uyn`ShxNChPj?T9KKb{w9|cIeptt94ju1p75vgr<9hHy<$OI7hkHLvv#}y2JxSNkwW)) z>@pPB=<|t7Ei?k3Npt(s?r@o+TUvM#7;>C*#@$8^n0utgavo_JrjPQDLz3X%+0BdV)wf(LZ=g<(_ML z%q{u4`+w&b@9rJlh^(GT%{5m73F=y`@}DG`Yb8J~xls>Qw@>=fvgp0P!Hm|{HRfr- z%ctBfIx1k4+z}q)1_lNKB)M2-tQNtLaQ~(w1r92ky#$tjO%UlKM>sU!k2@p{jN9ji zo=!GuP4^Rnp>!Q|Z!3TE)%@MU%ov?YgcJg@U1~>*PM_r$-Ro(sPD|-lz&hlomM6Xh z?-tI-M>yL@-LUX;B|yt`h1nXJ9TeG&&=1gFMn>386Nj9kPnP1oI=NBih_t*qxPAueah^V=`lfSK#kl=643N);hynsAs2cz+#4b zhvk{CdaY4OM2|(FLANMM%l<6XQ&s(oKCleilAVA`P_j*DOvoDf1pke8CrnH~-Ft%lr+_L^c`OS0EC^^ zs0wICEPPMPn`fP;h+02p)*qg&%)UdOZ^#F9;lHQ}@SwEsFUtlWJr$bxOZWyiqckf^ zq0p*JE>-3dpGm=>rm;uc(rDXN&+D^Vtk>Xy@3C7uYM#YFDrd^eb~U^OW}+2wft+v$ z_Rny@4&1#xxz-%WgY0OXIGeNvA3vl1q}b@f8%%;z zN*+4VS)N>xTA(vzY?qKya;Or}L3)lR7!Tc$L%L{!3B44^8R}(+cXoK!o|Ef?z9b!0 zy`Y(y?J>reG?oav&ukY$#cE^Tp4M^~J>8#icn>^#VkX>%W*6!SllLp}1PX-@k-52a zHG3&hxZ?KZ>*i@Flzm_Ole1*ed?wpF0W>=OcSZH;%r*znKQ7Y#-6Q|;)Q|6vk5dv8 zS9_Qd{}?&^{?(5-1y!2TSd7XJ`g~whe_~>1ty{|yeBxGfuHhfFXPF~=hCXFsH)QiFec?s%(15^c>B@>vT?Dt8 zy!&GC)vOY>qH0FNF>Xf~7<= z5!q<2L}v0m^O3zSE-qs6-{o}k;mKH2Xg2YFf36qy{tdUuwcuO(<6;Yc+scTE6?>KR zmnu^lDZ;UK*=>*lJ@7-+{@{FS;W|eF+tEb|TYto#UWIL8(Y7(>Pm?M>{%O48;trr} z|Msq+gws()Q}DuqhIdA8igrsXkyg4cQD4@JxJn=(pxZL@ACD#lc3+Ty&y;tOQC9lZ zf(x|Xo9|O8l})c9(NOqIwnA?3f@H*gpEZkC+aesj*S+nt+wIaXhPE+}dT!{zG* zn!na68#icNQI*9o11hqe9JZp~E|fnV@zy$j|MO@#^Ixqh_TL&y_|S z+6+)Gf^FWKLZKyd>>Vk2xBA+Hwav-%u79^;$9D)34(V=tBKKox{@e4lgoiMjQ^q9B z4+aiDX7t_nQu4ZmZ-ff50m5p*qiq!2UX#_X3#7&dEL2a-1?>$qlNDJ%%DQ-^l{Tea z8AqhwU2(P5tZ6hxzM`dS;Lyz}M&P23-9U3f9$vHlNE0b-2co^ZZx>%i0WRDcendyz zNI9?2*uJ_qGGS11<6aVEX24iYju@l8wa`-n=TwxbAhjEdd7P_v(}#T%GiL*DkE5~fW*|s`gbI1Z%gMZog2nGw{X>o<6T=5AB$ix zNMmM=Qs-XPAl64a6kTBU-ClgaUOQD50DB3~{{Od^+V<~2vg`NsyFXNAr6RjI>Qfgv zZ-PIIo_8z`Q(9P<5jkC3JL=tcaEuqCUneuUJ#cwK^rrH<@MYk1xk}8zRp4BV<8+h5ThwsdDTbX4mzoSySFK5 z8fYR82ey-XU?CjVvxH?I_oo2M$+>#oA<+Vh?BjZ5h4$Drxr{ZIhA}iPBIK1%3B|{o zX6~{n}>^O6)Oc%|73};5=34$9J0nc*;s`m z7T^R@akf&M3FOCE{o(nokJ$lvL1 zcD;8k8rFU$TQQon8AhH%R=s*8O1 zUFpTV9=coZhPCCUwaNS&9cyf`tHf4eKHO92k!qe1daCrgNvpQ+hmrLQps=Yj!bI%m zCVE|7sNC+|4(~aJjU|)bSvy^)c5WCfv51GniOIJs4b^IkH0yCRG&RXuo6%~z`g=(X zzZY0aL5t6gGapYeR`qQk(%3Km4$Eu5j3X3qBL5boKT^bN`vC{cKQ3k0`~y38%=+$t zQJ7u&f}_XO$PN1g0sX6z%h)8iC@94|$3Z_ADX zqkB8r!?jcCN%|IOyte<_43d8wblu^+g^B|f)_y^pn;c_3M-CcIQ+Ys8Vho>*Ooy%d z6tOJKaYGu#_`>{+8H;Q*(EpV~52GydF{!QGiq6+%hq%2TbJ6h@J@|md=ulk9n!#ug zYdi}{Cb4w=0k;Flb;^Eh3BU#m4YmkbkkRGo&P<1>tRP`E> zqun_@Hsd+f>xbyQ*06(j*mn!6Wj}cLh&L~=X()_YnV)}hWv#e|-@iyDpagt9%%R|w z7GZ~qijObniRAj-)03UAUF)WFmW-||w!l3szU|L!eCvE#5n#!1yExM}a^=|SxjY$lNlhf%qQr;Od9xLB zEbO{Q77cPOsQ^buEM28%5ddMSBzWTRp=RF0toh%__#62N(%h^rDB0SC@dlUbTV|W- z=BwM$o?Luu9#UeP9@0*ugE^@*THU4rr;DN=#OXu=jkyUR$sPOcC)H=)JX(f&n&vDz zM2$g9dyE6TRBS$dr_Mt!oC1=sVj#{-H+uk?4KA`<M5VD{E?x^ z3hdFDEruv__PYF5+C(rV#EsJ*r~*pjw<ITC()6ZDlWJ)r6=~#^?EFe!A9~O0;^HX& z%>s5dB^pHW@EW^dPfdljYC z9C+_FFc;OWnMglEB1tLp{@~)J(51-@p)``Rq^JI3y7@>j>l!la{4XaK9|)O5ou6jc z;B(Xq_1KRl8<)N=({g+}p$TH){cD*3Lk1a*n>235nX6@$ zB8Hy4#H-sj54T?n5eo924WHGnI>cc$Pnv1&k(mb$dHQg=tRxfBbcF<{wVCD9mzW!( zv6pOs(aZe6ZYOyvS(=5ApEO-=tURJxL|N@BNnFh?vQDI_FX&0%qdlq0S^Wn<{xR~civNsuG#x$sL$nWw^irKanQs!w zF)+*;IOC_~+A+a}AfnAEF!kt7+*dVi_zI8L8D2~;Z#rpnE-GPd?FDp!A0F=A+VQnX z{Hs?gyVkJ1j~O{KVwY9vv+^2ew-v!OJ`y^)-63^4!_6;3+-h+yU{w74_@`N0Db$NsGs08C`F^oa|WH` zG_^1B7B&s0o|ywB;6N;pHmq6!D!F%CUHX@*#Ds%RTZh+0vx(@5j~$3sCEfS;L@EN- zBBP_}YTkZcQee4EdNn5?C3mCl%9E>FYrAmyk#0zNv!dB&e|v8m7^nc-!3fH|A7JN4 zPP_{kZGD{XgWzR|LSV*VHp*GdC)f4uaOkvxr%NeP24MRPfM{ z_4aciwj0C(B0@FTQtI&Gl+#CwZH#xQ)Q#Ius5*RmRQkZwtKHK7Yw^fL`*QI$s=zn2 z9f4>BIF_k9^gw*!s5p|aeH&-8&@=K0@w4ga1@=V>%8Hx3 zz4i9V%>Hp+sr8FW$61Q2W&*}K#=3bRIeS$q`@RIZ)D@$m#ORUMoQJ>0yN4VZBB#sF zON%Jky`Zb*;up$~Bda01Xc~$A_tN>p$^Nb>t=tu)zFm57g|1 z@O&YXxjwpG7?c5Bvgvq+U3{+aFzM3thmh9bEMyMOu8WdkKqZw5>(BiB1MT|v z5t=JN*gU7~__2`U9=qm%Q-BF{%t7YpZ?vb?P(e;fRA%N9%LWwo+d%zh0;|kC>>RJ% z#NlS#*329(%Cdp);S@BGhMHR+*4_9cqkeIPm04wHJ3Qe3t?%1G?xt`P+kvMwkx;++ zZMP-puq7he!zB)M)Ul~)=;S=<#w0gZS*5(93l1sND^B?| zj~XFMS~sO{4g$b@F5TZrN=AN9YK7T8#GH^9II>^U& zVSMSD6gihRD~;Pu_~{FS%B?#Ev+#fRp}*f7%U+Vk_|r@$K6SzS4(1zH?v+7#Z>#Y= z#^)M3@GiR7G~B!0av|f*8!nsmi_(YTzg^& zCKzG8meemuX7}LiB<(j+wUp;gp>`P=StSiH_OOaLb!=-D7Zn3r2ycmK97!ke`n;kI z0vAM;kQQ;dxw(_3KgkP{$0UHpe9MqvIjSVuM6f|a?(tB;DB0rQE6LWg*PMrad)5jj zCqd@2KRFDPa=x88*Hj9LhG>2In1@+&eb$=(xdci)Y%@o#?#}~n%w*@R0yB@m;UJV7 z*4eb^1y@Iv2aK&5oyjmk{)|gX)T_2OP1ifZb%9t8F?c^Uw`;6)8Cn#V*_);HK)|a~ zd02Qy3#7>H)U+B_*IFKK)+%-8TmA(Vt@X~TiP81YPQ_i9q(`G{D1D))oAtyhTNF9< z{-=o}#?i#YMuPVhr!y-WS_hLb_x#Qb_jeu$s0@t4RaHcnEa}NcPnrljOgemu_OGf+ zh#~8j>ZCWUc6iUFZY@LhhSXd!Cq5$>R&#bjG+T2;y#C$1Gw9UeM7q-z=Vy#e%= zIWBhX1pCWurGCjNipJ*5+~}=|5ihjqKmcjh$7mp&)$81FLQG7ogK+KO)2M-QB!7bu zqlusbRJV&&j=&t6RAHaG4GnxgMEUY!2BId}fPP@TLo?p7-z3xM&`V0Lt;bXdb_ zO&>W^V!midu~iMDmEm(eN&;W$Zw2Q3JJ8@DF>y+SOdV#mhn zrz*o_RH`W(Er^w|urKVV%g*|%yC?7z)Ri&;R|~lQbTh2@?ah$SBzt-0gB1=Ls%wjx z#x}LuZ`2$MP8Y0otpg?qiIoZAPnipJ7wY^i+Y{LK44lj;H`?;xyhnqNarKO#{`G@O zWE6ceu<5&a*mZ-$#_?yKdXaUQk3n^BSEDlK8NRGz;_g8gOf+*;y=B+)eB3H7m0kO$ zm}lW3ZESF^nf1yXnPTCI;iQzH`?K$7Xjp0vIb+(-Jf--XfXfDr*p} zAz5oEqTO!JpvwKyd94-Lu%vU?guK#2pNwn##+fz3=!WTDk_d2351xnsZx{#4L)V^X zWpPJD9_o#)H1|Q_w~VVx1y)VR$z1~{b#!@K^)v^`a?(O*AKddu6A;| zsd?YzrQ}3}qnTpDF-u}GVIyGOK);ynV@smhJ`DpXcBYWu7n4A@UybK!BcakXmE5f= z-mfF&OM!kBF=1PuHi=yS0$LjA9P>bvIcAMrN~7Bluhr>YlNI_+|AL9v$$4stI5wo& zD7$=bF@LslB6?BlpeE`9O|Ec2HOEL+0Mj{93 z+@renl^Pu(yg|k~`+qw4Vr%fmMSY1MtI)R7;WS*=?bHv4a0-_1C{}P@Hdk`%vpOwM zNOS@R`!=g~cAwxb+8r+rWzo!FjP!ctIwlS(EdkcqLw)aN`i#0x*cjyW^>LC>Om&{8ODYlmz!KHTogcRcL<)}>crMK9>uG4LzqFY<5azVLN#aRHEfyOx3 zd0&R~N7{ww?L)_k)le70fOWHa>HTQy8Mn;COhOmIyS2=wsc{|~)ejDg-m;{CnJ0fz z8rz>2()07u=zGl9t){YwT4GndR?ftoc-&eH78DlHg^VpJ-r593C)H0*PUdF#UhHVt z9BG0PHlN?+>y2$vCdQzf)4uuYYw&DJPv$oc>pAD*Zxvk}Tj;DS1+=_sC%Z|0vctMI z#KnnDl~n%fv|gfEGhu_W-lWk{2PK;(xVz&oYkuIZVMMNv~xmO(NRB z;Plh7bzAN;R#XWJ&E4)3{R6rB5rEFOi;SzZV=+@+%`mH=^-|ya<{y(jJs4uG?&{@F|A=N8ms5^r2b%B-I#tmdh^8#!a)U=-=|*{u zbd%r7A1VKfBfoDfoUvI(gh%Mp3d5`dhZq=ocC3##4&8dT9_^2yHZy;b-xJ1Zi*>VyDO=40ccV{&9qk%C z+yAgcGv`a5Anjzp+53^-E}DsIac7hHzPH&(ot25x;Nf2*q5c)0jCz2hwkqU`HY#NE zEg7neI2xS`?|+2bs7M7i7%D;;;;|_Oxx(*|-e&S=*fRiF88^_&v9g|@oa9JvBidV% zgO`j zlA^JKYwLxYBNIM~Xs56FdC|G1X&U-8{=m}61hr~ZnlRjb5E?LU<>DS!wLO&>?GIb; zQk>W=xg_?rV_=`O-iO9`O$Ep`2;@ps`NFQl zc!sKAZPL31RMKItJ5kRtSURK4k z?FT4ys~KTtUs31q(9c7bg|QStxSIDp2h)W2iHuvOhYrN1zrSx$horPP0l2ka>-nij zFZB9T)*Q7#IWD1NjNSooukFz`G*YLBGszShzg(}t2Q#~1f(`$PkKx<_-tCd#w}LwA z+*KdBzn$srua20KGT2&UU`wqnNs$O+RU1$g@q)_39XoDA>wxlwPnI4szZx4jS+ zFC6PIv>_DJl5`Nid^{i)5;q%T%2opg<&_zyFPg>WN3W)cwr->dJJiTGkHcxaVe<t-wB zXqPXUP#MS{C+ z&DLgL#?8)BY9ebJP$NTiGG;ni`^_jHBTHcNfbUs|Tse_f5 zpkSIiN-=DmtgQR~_+#y#9Hj8-3-w#ktS&DvaqvdSeEP^|Aj=Cr6<-UQxmMkpSZ-wA z`gs|8*7p~l8+EOdRsW%M{XL$BKKg6=q&i}rQg`H=`)=U?zWakmd+rEUH?T3cmP<_K z5*UL_UZeWydx?fEdYn4O^GVUeGAK76VXztZci~ahy6M${`?exD{<>;(VAwcOZ191I z->TD@oLY~~ge`&gixfR$`orP@iZEf%zsRN8#b7S*tS7u4a}+WP;d7ay;R zv@AAX~@Uua}m zh0P4=DKIiIL00p=fMYYg?3`=n9-R7fy!iuAuv|3 z$nmlV(zI6?npgI+CSqpizdDLHe_;)bZ4`NbudmmJ%d}8a`vvyA_rOF9A=wn+>bd7T zu>q8Yumdpa>Bxq#5gVd^1E!k#%?|)_lvx$|9Z9{XX3A2Fh&bgw zu^iEV{S~0(xp~o%4>MA!YWu_Bbdyft;B6lN0m7v9-jI0-US%94_G$+quFni2|fk(nN zd%Ot2o40&M37k%cVV_4cv6)-5XCxH*x{X_rq&w#bF1I7}S-_L}%san3K_;fTS zo$H`TKW2Ozr}{g_k%EDaf;F%`BJaU%NxSmbmlaf?mA{#wrD)-~jv_bNgT|giG1z#> zK*jXkVfSpd1zEZx9}JJr!V0^UsgPac*bvn#?<;3wuD%~&YoG&Lr-9~j|SFPTg_806eI*Vzj+m^=@XZ#jGD8PqX~B*_l; zw_oxvJYmW?a4BAqCZlWo$rvzMosn1dJ0LwprfGReFw&77&9@9uC65ISOWb+lXuYVw zn;NFq2MTX&z^F|P3`x;;<-?8h{ zLWnKBiKk1&ooc!(kLHWFx~6>+fYV>9zWUy7j^*NK(5UU>R&YqsfQGO{LKihesvHvI zKSAAqJh;lZ2lhEPm5-}z-FO9zW`SBs)>0NkDUZ3l=+$IPWPxZ=@baFW!H#aH-$>%p zeSM0aJ&KI>S#wPhjWyMjRZQ3=m$o+11KBJs)XXr`vxqx1)}l?_}ZZ5zJf~lk?<` z*%%3w45eh=Dl_+EWmU6NDibm*omNk-?=fCq6xoUiq+GqJF#p91T_#n}Pioi`#(Ujx zY7MqN8@4CyoO|-?5K0bM0>^EWY%*Z_RC&+Vs+=T^E{}quDX68>7T?SscmoFyBF)1% z^~-Wu3aC}Y*s0O{>3eg^{vHU%yUwn1=n|B0QfwWplTR#K4fa19i~p+QOl}}>L0Qfh z*YBl-33!%IWxkXi_E8uz^kOwaydIZ)t{qwQ%!z*<#mPM2HOp>w;2q^phj%+5tVC3j z%eidt;xS9fr;izb9j18;7E*8Ud^=sam%m+x|3_%s3m{{2EIrIVOqd)LNNaIqmv`Y_ zTy*`H#QSka_!SxWq5W^VeNZYYcm>SBRy~kGreCy@V@Az`C*iR;d;O)8l%mas=UBb8 zhHoW;!XUXPdZ*B9u>#HDGfV%H)6U3-mtdCQStt3LaGpYvufshq%~^0gXl_4Pk|au- z5cdl9`skq5QCT}WUC1I-HK_1bQgLLx$vTy!vrH(@r^8r(;ljj|27%r-9Oaf9Owb}e zK@rUL{c+=gEZf;c{nGTWKUOoT`>m2Gzptt-g*Da_VRheBC*}IFV`av)8C=^ga6gwt z<}0JlV#bj9fNlUJz^Yz9c?>ltq9rE}8z-u?hutvO^cdxd-3~B_r zP*6fgxT&s7oGUK4v@Pm>F*nNyer9n#S;zWCT9k$=mAdh>Ik_<23Qv-C^Ows%o@4^{ zy`$Kdu_6`4sPS2L^EZ=yTO1MmDGR42mF+M;g(`fO7GX{59>RyLbiIcn8cQIYo_3?u z2to%IHKz%}X!IJwB}g{F;Fu!LcZOBgAoZ?MGWTg8g0;O$sn*5AImq4y?t=e{*L)jv z_sKH{TQF2ZLmpZR8@+XDRNuTU9WOkOS*8g$iH3POxXj_1ZBgZ)Wc7UgIpmUJQRdd& zx>Xx-YW+mnNY>VM@rmJENa7~fh#J%Ab*M?sLFab4Kcj4UIurY@%6aQ>7NReIf+hEr z$ol9ceydN=SVh?D@Vod0EsmoW6Nr}d*-xKbI8_u(evqgUM-@$#nY0z3$Y5?VW=cln zP-bI*YoeymWdT6g%#Q(mO4rOTdeC}i@vSuCcv*cG^LP8CtBP%r2(K$tC%)eUD$reH;ZV@2nuP@zM z!96X@640={%<=sV72N6|Vch&2PXcO=X@WPUsbVfJ2ZyZ-Lv4A?Vr0m^>gxZ?{U75* zc!6~m>iqE&#Y(>74xcs$gvWmV-Y|<^oo}KP*F)>RX?k_!ME6WGUNM8`5k%Fn)p=H8 zP#!Mj911)M^m^1yfo=HwyPVd^j2Q2jqZ;nlYL;`;hy*lne9IKk_wEl!KnO1ab^7V@ z_CR?tb09hmmHARQV1V-ID(J_s*{M*fhErf)^I^1M(X5QDa?VKgUf`e)v5F9Salogw z2w2{c>^hN(6WsMJzp^9&?Sw5fuH)Lgo&=5$S39ADI7Z;Tg2yX0mjw>|#g>*ai{o-8 zZ;9ei@#WfF4u9TvWSpI9Nzl;O=5IS$!9+2?OoFeIgZLlM&P{`;6AG&_v9sGvLW3Va=rhR`-OSftFpo-lDjy zgFG$~6W3QDioS|ceIjmc6m(Pe&4Sf@EpQWIp9Iu?{QPbyuLN)wA&BJoh_Z0xI7h?N z3JeVid_Twk3ce={_F``TI*B+JRhKTN{k$&a7N)NeTEaX0YpuF9ab6V$y7lg+Pc6{7 zIujI1H(m+|-hJ>`V@v`J0{Pjx$}|2nDQcqc=$8JrfeP3C3j<}@bu-%p6r-(%4PP08 z-x)EH?M)BWylu~3!%zoclM>M0Q0%LvarMgvpSsxeT5M~eiNqDDy}Kf}Ih_ao`I5Np zk8zq=+?_bRF@3ua+eL18`TI15e8%DmT-a)jc{t!3xfI#%hVC4{!V1>=?aXDVKR@^9 z$3-HyZ5@D%i`WB^6a|5K-|xRuL?m%;xLM6*rhBvdEV~j>E1uk4RqSg;!vJsUzN)mve7YS2rWQQozGJeOyVFD{$Usr&t=QW%gGk~% zLC**pKc~z&UloPW@|?%bX^^hEG?3=(e$L`h`!9<;Q@Us{?~XOTcQyfNc0}gFe7>|l z!S!@v&ABhs;T6lC7quM|l{v6>cPwvl5bGyV?O->R9%dupGbZBHJtLiRZsPO#lsWimqdYBfaI3EA<6+@tcef~ zcyn5bgieK>Rg6lrZ-sCz;V~d0R8&41UBtoG{nFIYp0|!SrM6pHm6>{>4a{>jeebrK z@Hkisxd(Ja_Ny)gw3p33Cwy6mo{^LY3t4+zfu1o_rlk6D`~k5xia6{WUM^&|ke4fc zRJ*`<#d_%_%jsjyT+GM|uJrN*+|sCAe#+2hpc$H{Sp@aO&+yYdP=CW*GF-lSqfhxCu7AnkxB7CD|>xdf34aUJ!c-_v^oD zt5(O-ZWlY7vePDThTGsRUa$JBg`Lum?fp!<54x)kw z1~}#2@)e|^9*o+R(3<6ua%h)bk$~Q|>F67%;(^*u<}HiXGJ*OR40M4V_siHNGxtT^ zEapP)&9k1nuZLkeGn|(`YXP1tRK^cM*;xM8c@OagsrUx$O(+h#ZgJ0$U+hiRja6e1 zAwQLHA6RKFll}BRfg&_W&9w71c6tV0t8Os1_Xle$Uo$IrCMU1 z0&5o12*<}YpHGcqh**p64h^yBbga^Ou5OGw?dyyWEHj8+x?9!;J(0pH4qGQ z(E9ERUSb_m3dQ}Tzf@saSlY_*U@Q{i=O-r@ZzlQt`EzP>k*m9Q@F+ENCuDT{YLt(YiUv-J>DmSQOKuXv6C{UCX}8iI`~I*&m*-N)L9@*zTPk?$Mmt)UO_fM@K`zye6>Z z1)RrP9TG)^%#O24mnJI`6y6*plFnE_aoi}MZF?D5GhX)#o_yKoS=4?f-1VIWVjG>X zi()KuXq{tp(83mzWJuz5v>z7gTv8R@`Q1;{8w+!E5%}*l7|7ZATOQ_WT}lR;*E}V1 zE#@!)41VFrqoRIj0<&UH3X|YHd!`; z!=mR?p?X1l@J0KHF$9auH)1ceD0vFI>t%6gP+7^hc80W61)tZc+7{%?3#XM31bI5< z!kbuJ2HNN(0fJ56`zZbft~$+HbULBS-RTmk#d>=KS-{t*$8*hYcy{yEc?wNgBdEee zR~;8zboH*x|IV0Du0V2rhSw79WSKS#J)Du3SHDB$}_{QE7s%F?==4&p0sn)It!X#HgWpmo z1_}Cel-mzC9PBRF5BBqzF3zi9pX+54uca(HJAVm)A<*xOi`B#AG+;0`^lm0sRfU(0 zu>Ep{$kTu;C(%(ugB}hI=@(7Je%CLm4B*D+b6hgSCoh!Tj7K$BxefbQq4Mu~MXpc$ zYUIUpQq7)3SWyxcYHkeJjmgCW^Ejt z(eaS$wB0!Vh_PXRxu$}P_UkO?Bx;U^)swf)4G!_3l{EZ_2%PUfKVv)Wp9ESHHj3WY zWr@3BYBU=MD_8PuV4pj7CG*Bi%&-_a$r~Cj>rofCzrpmoypje=NIRY+gc#QBOSb&< z*nS~1qdv@Ktf1>yljeGxN#75hsmf13iWTYM>di5^-f>^rlq5eZxcLc+m|mogagCgI zqZYQ}#Uj!ZPZ7TcCt^YDskA}-U4*u7)XmX1TL9OTB5r$kdxO#H4&JCBU&Vk47vdk* zIqqiD#hRl6SGCa@1r#xX>pF%EV(jGkeW;s4*!uBD2}Oi;Bn}`}RUxm{9Wl-wZOy33wLcW2LF| zW~VWGr_4i?cqnwQ<(+mpot3+;Zww-*^FyM$nRo=W84 zqJ(Jk3w`{*ble#+EPiEZ8gR1Hav5kte+s6`s~zym40DKA>`bw^A)*dVxdu>J2^{@1 z2cbYCI6dcciG6E(60gs8J1yy2BU;X<#Pe|jY9=@0h?h|Dy^ZO8Z~L`-=X`Iod@=(% z+Ivs0q2uX({Z4~4MBw@Z;ibllm1kS&PFj<)wd>jA4*?(RyQcY<36Or?0Z_E*(d{Vd z05sxPTL`EHiYf3KexKE- z27A~XQfWEgJ~~}vy89DfMomAD$AC^lu;5KgsJpx0$iP{l&tD_kga4E<0DMn*#E#oA zsnf$!L&+Y_vMN)v94YS@1dAYycaN`-ehp73BEGWrqQlr!i$>*iYW!Xd%4_vg`J z0KYC^YGeCLU;#%~^I{%(7oF`)cjuN7+xaIl2ELBt-{Mvt-nMa2ZrFT6An|v(oL^8i z>&iEr|5MNVl$kg749wU>=Pt=pH?0+78l$EYZM`>idBg8hzlq@hKq5{|`d+=}Z#*9$ z8QLAMQhkaku=T9c$Y?8B!y2q#y?hDl-XXy?#@O{x4Z^~X=P$8&5|-0+QD^T)p7H5BEeKpBPCbY$G+ zinFp8PwV4`bm~=8ZcJ#V^<7)b*Y4*NY`b)>65AtJ@7;v^y+!JicyD&=B5=G@FtrwX zi-{N&8aQRma&pNSyKH9PUqUd5N?w^!G1N2Nlp-QtoEu}@E#j&;cx$k<)8*K9hM0}`5>*Bs@IgxT{>1`^-~ z{h}apxcHhLuiN&QDn$2fhMzOLx`MPK;sx<F`0NBa{Y@O7pw3r{1G?+lxD)+ z*)lxsi*4Kl11LuKQ&@KTIs4ri2jaQIBms`kt zewPbqz*`?=FRg#<0TSP;?r=~2R(gj=zJ?@RZ}IQONqm{%D-U+T{gW15MvW&*-I!-E zL8$rmdVZ8O6@YxIZ-pK9tLPKehl2=!ge`8^TKfc1QLZ;`E^w$GV_ zsbY$L!jfs1V8*Gg1s{E;R$?1gv;~sC=NrW2{zVY}3K8O0957a}{=Rm6)@0r@q07@q{Oxaey|sb|8c+#@YK0EhM7hxH z@@LSi5pepxJ?7qvFM-ZV-wHj_{1E0QTB$pg0AG_NHSS*_bTnxygS-l8 zLo_lUc14z~xhDBu3N+3f+Iq4m{%1=VMoz`P> z>=i#gl49+Oa1~x`UzqVzmP_jh_Hy&+qF*?GckdPK@M~>nX`~3 z3_#e7svn30xOj@p#?kSQp|7pTPn+xLa;ZgfZ?}n-fT<7DK+g_-e2+CHV7;Y>I#J8d zgMf_I5S+zf*-%}Vc9wXvB_wxSy=&-O%jV@_MRW2RU4*SfrNosUemccueA*`DP&{#x zA#<~m=dM(6{tC@75bZTqT+uA=lJS)MD032Vs@0b3KTCsq{5gipTC3%!j37$Fw;Za8 z?i*{8Emv*)_AEWWTZg0kXakQb+OZWmycSr5Jr09bw9DK|JPzl9Z#85jOrmxj43Ob$ zT1m)3I!nC2L)80>cRKn2kjUeAGu(!ds3+wx6EKL;O~5-^uv-iGXgmvVn+bew{cSUz zjC@(-t@WqoK}PAnG38&?KO!vXI74bvRfxfsL#aYJ7oF~!fQ&>+ILF)YkbJmm(nmHz zwA{;+T-mNyFJfW66}8d#1IsZ>;J1p#A~lxsb=MJ%P4tYwbRXW4C*Fj-=A-$`EgtY& zf|Xr--y^IHn|M_Xu7=@U3Y(ZHRwlh!jBPd6sF0F+>fDNsAgJ)}c9Fo(?Uw z(%yZQ%f-V&B^2&Rd~6#pNPCm)UBb6hdP*H)ll;OIe^!%<*Lvnf`}?~KtKQbHYV=@8 zgNG!suWR~ci^}Z$FZ^C*i6yey5M{31g8j-z2?_^th)2*YOb-NjI=RqQpr*{0nCd16 z_~hjH7=~=LJ6B&7jn%u!Ckpwa12T1x513;KDTDk>j%c$LRtD<6qj3|%Whv$w}@{$fj~B=4`s8wZN7_5>8JT z=)`K|6WH7;D6|)-FDq>bQO{-|aa*rMu(}@(oFA;*mIB|Q&EuZc8hG-R-#42t5?-#KIDRUlzwkU}X8oHA zBT^nIMP}_qUnQz^BO&+l1MPNzkrC-duXbNo3*FG`85vZipJlfj0iIicr|xS~83xUU z1stlXKPnxrM6e;fGR!~n2hC@ViASqU?)hPCfZA$52M5~LqZyywc2mypS$}2-h@G26 z=8#!AS5Wl>$>`hA8-YsR0ON6`cV<%_h%D)^j0#CvzNcatewU1?%jZ09IPT*QODMIb zPv~SQXdyvpSg_VXZ{1}hN|9~V?Zq2!(r7rP|8;MJTzko=B4R%f7<)^^cz5dKnYpoh zc`fh(K3yXmNqrqDhfDX+=c<74S`7X0@o&8h1O-)CC_{jQ*{fe|9fA9HvuvU~kuE~@ zXmXOYJZ9+d?S?*6Gybz?TzKOd=5|QSF+Lp^ijvLLShrFX|8g=;##2MFr`%+3tUR8} zmGj{ln7Vb8gNoekCR>??Pok;0DL3!GoP6ETH*+XTT|wC~{QIRtgGjyxb>Zk3MJHu> zvUAOiTB}_s^*_^+68S;w3x~UKpSGQO>+8S9FUsT(K~f1T$4L2AM1#`{r3-Ws<(@Sc zx5maz^2VFnk}y13LG(8sHIsts)+D~DUU1E}x4sUI%h@(ZN8i1jX6+Xn?DQg@$+5xs z)0An;hjVEsP6kPbYKHwS6m`@g&V`$gb}1&DkxqS`zN&PaH>I=A)E^t(I=x7*j17>e z+kx2gG?~WOk@czClWopSVL@kzSYV&X9ti;Gs3lyJ46qA2RJHtt;>}6~BD0cBRmx1= z<_WvKyC$eg$g8W;&Y+vgr;$0yH)bt{HFno3DPNbxjIX5YZH7}a+_lW6dnjvpU8P^g z!cOe%06g2!CWY`?mww{Lm!do{8gnbC7~u-aS&D%^ zPcDaDSomQg37w%TpPuaTnsP`>$SCAcNljLoN7u+u_!1$k-lFw$AqyDeJK?mUwvf!} z6@c4%eta^vPCrXiD=9+VBBHrcKD0t z=H{aBA!ydnU1^(hZoGdt)4cmHWWvX+{YKSoGCu_axA)cWE64sbL2Eq5+$T1*Q1GH* z6BwBo{f!)1YzG4wP+B!PD|7c15_dAANkM%K$vAqTO z_LJ-Qoh*YerOZw|;Q1ZYl2Ka{6ttd9bpfKkYu`s!!W61O35a z0iVQ>3bQKl!@7-QP|=!UP;w)Mv4X2>72=-pa*S80?y}g)c0kgFVPlqE7?_fJ*|gc2s7B~5FEXeLu9QLq^Wj0Z@JAP z?YQCFqj62HwPTyD6_!oR-CIVEyOVV1FnFP7OkL&o&imZYlvY(f-kR~hk!f}YJ>$~@ zV`POM>E{Wx>-(F-j98cpy3y(8hZEVXS(aDO0~s#TyYTkt$+OT`RBc1|`b>sD z(yBDn$4#4g(uLl(>=axSUC0R3*pq{*@|WyVj`nXqjD|rV_KV3Oi>SUF0&e+>O=2_S z;OZg1Hu<+{)|LSV6@%XR@lBieIHN-68_4>aVq|~fpqXe<7UIoq4fLBYZ_q8csbO24 z;yW0@ApoU$^RPzwB75%9!LXt#l(Z2M8c7z1S`3%(f5Wqfq_8lor^$VyYgNNzMN%KJ zak|l%d)2-t5DsdWhY9!b5DYY~(cy=kA1q3`dLB`wfJGvQpbD3F7j@r-UW>t;$)g5u zN8VQJ$USSdm?Zq3;`THe(;h2>T_b_&o=py6Jzk1aYc(?^8mr%$dF6G)^=oJdDZBVT zosl`7doYnG1&3|lyU2s&Quae6)BYt?XIqr!%{&hr7|*e`A)SbM*7DQGs*X(#u3NXM zY|g$XHf_Tj_GR01?&h#U+Tf(Y{70YOo8FUw=I-Bm-kG64kqNm>-KqyDPF4}P6&@X& z3WfeA+{i5|!~sN6@rUO#tyz+?lS?52boK7smzv$2w#Tx#%->|5jESllDeE_cVElC!C}BDB_kI*@bnaay1rQ}d);g{#Hu{2BN`8r&tY9IvR)`L zBY`C(tI_56nW#^vVA=wB4Gq|}kzjz0M%y%sTkeX~=g{3Q8a5t5h^=E2R&*|A`}f@? zKgaMCAA=~oi>Pqvj`B*HiZqGM`2EBuZU1>6|7ypbD90GX{BTOa@}`9IuXVd^zPPT` zP3l?}Z;|;d`+`Vw6U&jj(P=ntDfa%yBPrNu$31I!(f-$8zdl@E`7DGjpXD2P$cxRj zk(2mF*Zi&2+?BPfrk#uXHaN)K6L+jT=GL0eR!B-f5NOwIkbom2J-bsqxLaMb+_PsN zZ~Z$E;SR84YSos=32@W8C}2!F=p9mOw_5d|9$HJ>%FJuY-~51|w!!#AT6qeZ$T{{uW?&HyLB5Eg(K*zN`&hh?l@hX8=h=2aOq+}hYyy+r zo3WOM?`f1RpH|pkS2}9Je95DN#Z081ee4fpOmoFt-!KD@qb=GS$eHNW!{jj@P7VW> zgfBf$*oV>Sn!$JD!m%(k8{QG)SMul20~?&NOmgTmIA38&4bwxd-@mPWGh4&njvG*F zSYSP_m=`}=d}dzJZCkj` zyOMb$k6}_9U}j7T&kWQ6s}bMhr0Jxc2`USKqto$#GPuyJj2Zsf(Q;B`qQhFQp}Cu; zp6_baS8|lwQ1*-LR6xR65f zzBtVtiXw&J2XD2ET1uL|L#~NJLcT|~U}5Mn3*MwgAFS3Lsjs#);mK1gZN|$fBnkZY zqxdUcUiP9afljI@#wHS_+~sB}pY8OLyN1iqHmZv%3%XrnX?-_oCSd|w*55QN)U_Rk zE!83~x@e`2Bn>3PNcLAkovW$>Z}tI=?q|mgNRfgJy(xZ>=x$FAXE@cokE!0FnE1iI zb1INqkPTsIfe&)+;V28Sv8XFjylEcEd;PTtVw~i6rg!lwsj74<`NkwNE#1k&*QJ$O z3e(O;idK3Cx3;$~Wwd3rL^Q@zylS#HET zhkc%@2uZ+uxq7m$0n$Xd+X43ZEnU6fSl?89Y*-c}_QLnPU$mOqFm)OqaF_R-d98f0 z=~?L6KsX;x-rz;E)ZX*Mm=AL`>mNGT*j^6a&XMbWmBr-Ax-UYeWb_Qy-pqUEcsAzt z5Kx1FckpOpgd=!=wEY~D{l{<|j2ovz8ut&wl9ZkU1Bn7@eKR#hV}9B&YqG)FPM~Aj z#v63Dlxl2ll5JYQv;q4ow?NB>+o+u)R-3qEFU_eRj%qIfg`BH(#$)Tb?|1JCTpV~vDLYQ$0y21q%^!?koCf?BWFTjFqZ+LIr(I=1GKKB&5_UMO zM)hht;JqylAi*dE2ar;a!mu`Ulg!vJ1#1v*wd}EblTf$qmw+Y1`V}74EBH70sf7jVRUGHJ(Ug5F>84?zo-4=Z6&Cn zuP1p0WzLawjJ1zT;E`&m(2@mwmUgKntfXj7X%Dt~zY^O1x*fxDUYp^#- z&?~33zKzkzEAGQBAW@BhZbYDsAoLU8C+k>LXq^==eC#jVByhX-YUQJbCtK?oBEV^L zr|bnilBI|nir{@#H=a&DbGo>US=Di9BsarRFur>1Ay()N2~Qwg*=gFbf$lU?m`XS} zUAoh}2+;QvFhtWUb63ay_9bZQF2&EuJ^c2o@Z}iLJ_MO4YVDVZm#M`h{cs||arBk} zde3kG$Yl{UY@U^uG>y-NqDQ0=b5zCa_ei+wZJW%N2LZ2{33h^Y39Sjo3F93$!ux7LhX+B z?3m?EY6ZA%n>T50UY?+;zK#2ztolUo|C?1$p50V`Yw5IRRaP|^e{d)-xB7t=tJ!_> zAQA=^E8nA|eesA==5^bP%Fk!Wm31==wA}ypddL{i>4+&pV*1s+y{X`km1DafOB0$z z=a0+YD$=Y&XIX2Hk>R&3XK}Tcp*VKe48SD`CKnE1xl$_Q%ScO$lI8X2%pd+JdW&;1 zfTvvIV|PPD8*GUQ3cS7b)#*5v!6tG!&^Z@>k@za=vvXC9s59rtHnWC`?!wsvU^;?g}3I7sY0EgyiQcfkINo8&`>?S&zc zkx+C4QwJuw$pm4XKM_%|7oNZB=jld)FJHf+d+S_mkN>`~Sx)A`wdz%TLz3T$X3E&y zxF6PX7wNsDn-{PZBFJ$XS0xuO_TT1#L*ZxT%m80mWtLg{_nD&Xpo_8?KDnD9xy8se`tn^MZSYA4J-vo{3+04p$(~c3-GX0L zt~4@L4gDc%KbOi~ZiIq%%5=*i^1dx0B*Z z<7!SbGXN5{QqhRvEq9<9i!$zM9Ob;euaInKR3nZnr-u@D_h@ zD7mV6`QwAo2vbsU-1}9D&x(GD)tVg&@q%nKH6ZJTN#V18=f-@0W|yEl9pxk4`eH9% zv&jScJ-)9}y**AT_TJ~{i#js){?iT~=V1wX=F~o~xod7c+%mx~uRHsH-Ncx{MhaEF zSVgqh#7g#G*`g_k#S=MF{|bCOG=Tp;%lV>1h~(O!imvPTBGxOjDhjWnj_xT(+pZq= zoDhC^uy5g#C}FWa8ERQEQu0)Uj)A3K7?pktWLL{gziz_$`-ty~)4+J?-oFF(eoGxZKO zJ=yjHr~E#OKzdiQ(-*R}UT0`a)5Iwh>+ury{q80$)2nw9zKrs0m^Ae^C@JB?p^BswXE5 z+}d|ugTHjl*OG1ySRW&rGCmqS$G`rJ9We(2%w^y?q z*fFk+Lp_?SqrwGf-r=2_tcz1@fSn!b3--g78$Qq7aev%)_A3cO!U_9vlZnDz zYrT63mG}PL-PS*FJ`Z&4+Oby-5m~tNnX~OBlSxLxz{c!F=`RGTEg>g1cd=IQaAY*@ z=Nl>SE4J+ax8h;w8FWWNyU?1W1*{6o{5Ebp202(D9DMWm)GP=`C<3({=aA zk`GKt|4fi5;|Zc+3?6c^;+C?&aFoSlFl)gO!Qdj#U@TwxcLe&A=I^=1J?`aH@I5)U zzI#3W3F}rsHH2r^8OWMDVe=Bg(9vi zG~W{wQC`0W!ukM2%my3}kpcFFdZEE4?k&Y0;vEcL`gunw974^wJ-zQlFCf(!o5o_T zHspTAS21OS?`Z1`KvtQ7Vb0ee^Z5Bb-nIS_P~i8d1AXpjB(JtCh3`o|HFj-%ouYFm zKw-Ok$_EO$X*e;azJS!xesi@*arQpI>r>2!Q{d|!>L;AdE|V|LjB6G3`Lq*HgHUkCrXHTP#%cX_xh+EB zwxzZ0Ye9n@ zKVoiaK6jMIH?)hQ6hueb(=;jaQM7%RFo{G3DG2ER#2>6W{04==K&^25>1u|l;wYlA zPgxCodvly|(3l^pr;ecQ&Zw zi+wim(4rBRXAqK5c8P|xf`_$Cyep!y{Yh-g{E-V@?P74~Pg{bKK5=W7c(-g;7c6S< zNR@arI3uAGECtN!PO{IEYMFe&GQ{h~@%hv&QRohh^c$Sly=~o>p@3Qhdu8~Bvfg3w zQGrP-tw8)6&Ft8yd!)w&)$~_uRL(~x**S6cTjin%Bq86uF4vum$rPoP$A+Iu&3eWZ42RD4DQXH_pRB*Sg9Z68 z3o^Yc>wB0_SOL?O%ofF6`sn*dcn2mp)mA^uH-1#bg`2(0Ll){&Z!U|20%lh0=+3Sf z0L-mB9c88QdVl|ay+J_}t!SmbzS#R#lZ4@fw0(NIL7!e8T=2%f%0b`StH?6I5S0h8 znI*-!4f(aLT4Vg`A66~?g20|c$0NVPMRq<$3WvFw2AC@;e1ycd^qt!{j>UU#nCRXL zmwmmx|F||i64h;#mRWvL>a^^NTr7#Aslxfsr~FsEKnFcaHb1M<5f2dr4&{7Dr?Ys8 zSU@(GSci+hyN@sL4S>Rz`v5`@gkYUCH^sy5x5s*(j!S0n$IAf)H2!bYgO#ms8B5jj zaC;z{l-D;CVJk0XVqsDlHuq*O*@WX;-wYw!TvvNlL!MB&S)^IyYtihYmivarHUyNG z2ypigZRq-}umq|K-ST%8?k}A+t)`m~QEQA54>{^=%=cv3t6L`8b7NVYe_v-{O!dT! z@o2kew`vY(Qk`yg&Xk0^R%oG1SzBLj8891}y7%r=l0EgeyT<&+NQNZmX2V&|aNpfD zw~=0LTI5B(5BzO!^s-33*-B^$F4oP(xuMoCc$Vv`KV_~BDJzC420Rc>=Ew)(taYx6BW2ING9}}-87n-+pxJisi%+(&zC7v$zb6i}EsZn~UwNU(O zVZqbmwS9E-1iUKD%S6g&ca7DxDcv0;7ChW=f4A9LiowIfLR~y<|Hun@=dAC^?7(+I z)z;*It5uROU%muB@Hw7YOFJdQ(uE#rZ}wD0rJZW2cpyP~>+7LZAxtT9*!r0W#nCl= zg{jzh)bt)t$ger{xdvy-^$i_gy4{sVAzgDP!=0t8S2AlDvxN!iszm;c_dYm5Ws4r- z0s2{SbiN3t@(#d85{%?)OI_N`F3*SJq#lhz*^KEDZ3zpD{0`t#9#Y%CGr_R4F!@LReoh- z+Nosr+UmD7`h4?Uh3as{_Y_WV1uYD^0Yqb=P+?qQAQmo*5PcsHn-otw51{N~fk-;p zjaFhwJ3{LF5#ebU_tIl9MM0JHNk_K~R* zcUSG(d0t;7XmUBp-ctBTH+)--0K&su^+lq~i|P;OdKoipyx$xD%7kPNHqlJiP2Pb3 zIqn?C{kmxV(4X(azx>bqo%buSx2Mv;k?apxi$|wx;m=&ZHW9w0Ed!iGtg|Y2ojG6me{2qPXPJv)zt%`${|zE`-6j(Y*ez1z+L_B|I&#A2 zX<6fpxAzw5a~{6iwx@AKUi4X)3Nv*Yrf_IcNr&X!RHeD?kMj18p8$p$_eZ_YP5s7f zaH;pZLh6c}*o8RYi}WF!T6MIO14=^CgYG5u%VMji{N4K@ix$L$S36a@`N`&ePARtP zqg8H3@${y_lud)*0i=+{EN{A%=i=y+@1?{m2u7>m~F_N+g($ zW&585{`u>z6$7dlW~xu=N0r&boKHMbi4L;~c-r~OuxSZ*fO77W)5Q>^djN>s#SqUZ zC>QvV7R4XlMmkFfV1N6IB2_>A&Klv4xat^W3k7?sCk_k|i5(@bYsp=$fyGU7CXa#w zsXyF1<^h+NV2)}H*(%H-Cj7%VsR3>>#JZh-)!Hq@WWyv<*=B>9{T>NUV{*Zq5rD2mD`(TW%kww#TMw$ z)h(5$<4ghKY@bq2Z0nojlvLSzNi>=V6A=-fx-;EmbO^1;!DI{hvU(RrlQ$GKrNLpg zMg157MuTlqm4mC+yQLpI(DpmiyiY$LVWh3D-W;k3UpE$vK6XMNUL^8vy`|vy5?bHf z++~x?53|Jt9HHp@?}Vw;SY$7z$Hid;+|}S1(g#)&t2K+uB+%Y8I4TepeS!o% z>3;VZCFq8=AD*&~tW^4of(#C=pOp0UgvucU8#0APenn14cQs`y^c6}{9*ODOjj)mX9k{#b z&N?jltKRX+3CvyLxQUAiP00bd->^G#W?SgxbKV&s?A|&1q>6)^fxz)ncLjR#wlRz( z>L%JjaI9v{U7$(U4_Q^41%1}quylY>dAGn$NTWXW5j`>If-fZWNhkpote}mLrlO8O zhoY1|pBC#49#>W4?xz^(`A#A)-I<_8m1~h?n~=QN+xGu8OlXG%deV&v#z-6Odqi4@ zvxa0U1ADM3Lcp5L7-|NG_wSDq@(7%6R`dczY7ACo>+m~ZCpUX!U|0vsnNU2*JO$}T zwBlLoAX&r3RYbbtj0U2i+?w?-g|E23^Au?1xqL0~(5ghy#fxaWIWN)dbw9{YdpejO zD-%ql7+Y&UNyaWxQW9sjgWz_O=3Qulyna$)r}OBR78fQ`OP#wUYl}mc_n)z6Cg&%Y zpqv*_WPD0Q9x!SD+cScErZS1S#aph%9K=qaTal)UK;0-tNR}sB{N*{g_jT^v-=rurl`?ZL!o|6uJG?PRnbddt z1G{V6)Ml;vw;h}s|LzsUY{x?paLV7Hp7^g#ue+bf9SWb@680|HsAot(#i#%_!05=h zAXzt_s4=kiR(ll(o!qRA|1uboRS_B1D<4o3;xj!6{i*HU^Y1OSe`D##8knhvy-h7O zf3$Rk97h!|jW!_bdJnP7*p{15c*-Ka?6*d<-!$fKXlcZ+u{7vV8CkkDMaFZItW$cV&7qdRc+br+f+?DvD8;TXw1)BuG^sQ8a z*?p{w66T)HDDO??x5W&z`n|d|1{LjInpCADLHFy-cKBk97Et?E#U#%mo+SGg}Ci1$%1==o-F^%S(frxP|UHh_=2tr6yC_(Q@P-oh7& zX_JjD?kJ7$R8}VkTYYKfe8JFAND9ZGyM)7=bxXTYquDKR!C-Qyertuco-kn&TBb8o z9Vl#{kn;Q38^UK0-tal6l}n{jMWDU)B5W+2=Ziii8kRqMRGN=x&*>9H)tq?us}k|) z+&(9kw*=LbL{}6;&)oaNwv17GQOt9vGZ@B}!&&aGi17kh2X^CziV}XH_Q+h5u3@ z*LQacz&oz>c?hif+Xy?pdSJ=d10ZsX$;u}kb0QCFa$+;=KArUH!EmH3oi9wlpM}|cXm6A+^q`xCXz7X^68Ihid8u; zZ03=}?#U+=GCY`RAu}&)x*`ss^_30C&~I8&oz&ddoHrV@oRmv8EaZBLtsk)GCvoUL zv7G>mC1WaSTq@r^aC62s5@Ih~3H^brC|_mmrgX5TKfH)G#cDsUJ#v~L445d|BnQup zuz4@W_Jh)o$L?hFyLkKeWpv_Y9Zdwt<{P&u-p&sIedUAATPeRmJ9j(0o2xf(ow7}lt3lOuu$14AqTAcS1^;|< zF>*CI#=jAHQJ}>cGGcI(Pb~yxYC#oUS3s+MQ~T0L#G!ez#hb@<=tIcNQPtz*?t~yUhu;{2qLN#uavw%GV)nkn%z3bif2^Qe_VGqeg zi^OdbRXoXT1nH)iY1MOf8r02e{QzuWG)?HM6z=C1F4Va!Jw3&d6Pqc3mjE*MvBuo+ z#;>LVX1SR4WzW+-#z63a+za(@ZmY48cySEQ9Q#g2N=0@g%rqh*BIrGVzA*hb!Ey+Y zklbJJ6D}$%(+)s$hmZXZWE}8#%0t9K#;8HbKFoDh%84nf0c_3mf{s$e!B{qGQNmw> zkKR$=I3N;!(G@t?!SJ~BWMG>U#+ddNxv=}#_0S!s?=wv&s|Nu8qtnJ@HS@-gzpkoF z=~xNeAL^sXsDqF@p|)={J`)|$j(J&K_09k9X3&t$i6@r0O+3Vz_1)|YEAoDSGYi{( zMswa5$Jm1_#hq5eflM^isW=cI@Xr|C9LsDWiWc!*n{2c4{uQNM?NWesqBH z%X~k#0k(Iz>B3#edobZC$Vhs2;3rBy^8xWJ1#UT<_Q0(W;OO2-ggJmrAjQ4^CxNso z;HTVq24R{KCbdu@Cu-XhO*uC0oc4^q*Bc&oxO#qigJc|p9tXKU|Fsn>K4zj_D_*P9 z#X4(5Aa;9+7y0buy)>0!Qsh=zQBIb`UGwhzQb~CS30F;Z@C>_Xjo{YZ>s^mGtXkez zybT!CEw%n6?|=WMjKG;*F{m;UL-{ZZ^9%Fhg-ZemCCxiq=%1 zTvOzH-1cWvfPv$=G~XL2sKk6_^PUpIdlfUhALFWVdKu}as~<35zJ@F*Cw82De>Rb1 zbn-oK2|_3S2$HRyp8=X!zG~CefdHV4srYyd@HQsdj}KafAf8$Ik)OH35~mo15VON7z?~ zMcHkAOGrtGpfm$2-5?`544@#=f=CKO*GMBRAs~%(he(JZ-604vboU@NbaxHtcjHs~ zp7WgVy5+lw~(O>}<734dSrI-LEfQ{bD1i$9wd- zi05EqfGCbr2VeTR8(nk?Ephwyv>092o#tHCEE(G;s5aY^cGB@;n4k8*jDz|jl3+!w zoUYdO%OvL4znPel@We%N_R6)kivEPR(iuG#x%s6|~ zlL`!71-VJr5ZU0ljd|OEfY?-z38hkc*?2|T3bqz0Q0~n%*V|&q4>^!z$2EJ`&lhZL z4fggY`?AHIs^)>wzL*~FADF3E9(|Y{_z?JcN1pHQ`;C{4c0^x*^iDM?f@GwtdQ+~f ze23s`NjzV`w@+BV#Ee_jd zVhkXzTRj~Bv5Tny4KnX}9%T7u&nKj8=n8q)X%uSJVL;G(I+|5;AYz6JA}k=s57jg# z-$0gQ?v>KPD~r{a5^cYzg99NgIjmJfu&72I3v|TRAI$5xBbTaN)v0zyAZ8Xo1Bls1yRE{#h}yCz9h@Z_~m=hrKq?>#t) zRrqC}DZYM_mmis$NZ?vS97GRs<|q#CfyU-nWVod+McTRCf4^})bYWsCYWcm=#5?6# z_k$oyxt-nj9JBlV0x1Lh%GxcQihtD$Wl&-fQwWJnW3Z2ni)h{cy^Hjp808<@v>66n zit}yBdO-SHA^c7(Mqm(3JQVBRxI;V8Enu(%Tsj-&aWIE1J?)1t?HBl&Sf_FePev$6 z)rShNB{eyKi2e$lXo{+3*7-}6sSChf?IO!veygf}8J`TPdRyMXPF< z3BL|Un^%*xjgKtIgNJ%c+Ix*)Dd8q`$9?cUqeQDw)p}F9I!8}y;HoS=2M4xhrC?r_ zM9PezZ;1ITOb(h4?lPYae<6ysXB53Nf@s40*iCpBY>74Zwj{EC@xDi2MD1s9ctlX+ z!^7LlvAqF(rFTzUp4{AVU7_kVPh=^C#r-oVDHJ2{8ZF)Sm8WClb1q?YJiyVw|363L z!^_|x?^Ddu_`9evnKi)-HAz;kJauT7^iqm;ezfZ0j9b0%Wq)>9O(|e)WZuVlZnvuc z1($3%y+4;uWy`z?$6Vm4#MSaUk)Ki5Kkvc3qdY#XP2cRx?d{Klc}AqBoYSdljPi|F zxbvKs8Vh^ueZ7y7uAB{&Zi$HzS~8C$)EN#;@ws&Wn3JDr4urIw%T+~9$T-^Fh~O^! zcEH3bv0*;ho=&hXjI$n7(%&l*Y~nxU6uOv%UIvetmh4sS4WY+O_Ljk8rXWcRwHTvtK6i(%tRVGroOTe+lObPxFO%o z+Rud8ePZum@r|rYR!sIVT+BL8HJJHPa+319mE*p6-${^|SH#|x^nWS1wn=5W-3F|zisxXP~ z)W!J|5jz^rdN!RY4DS&PgcKiLmRe#rks zZAUBgP6zWeD-u>6j*FR(@&%lYn!Hd`gv4~eBYWh=PK$_%E!l|(hl#IOSMIUUGyrvQ zR7GR81qhfp%TfZkR3N}wB-|vw=GB*C67*YfLj4}mw3)-2g#|w|d0&!&yV-ku(A*l5 zuNZAh{r$Xeg5_WLN2;{XlR^12Kzdn&0uVizZ`gDQqs_GD7JpE5<^S*p zym^7@M8FXS*~~Njb~M*nvBc2p*Ac)biPFxqs@-3_iLgv|lOr!D8s(Q*f8}uqoZ|)0 zaZu}FGl$KuBRa;jrncNvm_>lFnlW4Iy+uKw~RC37r^A?TRzAzisI5QWkw|HI zht{lzI;lNSCww4-0Mb_zk@3-sMz%grnQ`XV!GZbshjX*N5{yniz{mZkAtQzTS4FeD z_EubCoT5{nJzQufhH!KHy3yYn_$cShQiwyU`j@>|Yz+MzT!Kx`)&O;i*1dL9mHB`9 zTmX$pus+pfy9ps`7pnYnG)fCobkWr9! zA7~!;pA;l}R-`HRl9zZ+-$T`xt|GkYhzD?_zI0;7}_iK1$8D>D^EIn~8>yOgf- z9FfS*sRMnZSIIoI9|Mei8({1v5Fbcp>&i&aTfPwnF);#rhj2+ruW*v)t538jZQ-ge z{Kh$S-WSQQUXmn#e(;Sztr%;CC4AKn{*7}v_NpXH9{b92CQ}4Ja3;-vdidJBy{=|` zD13mM_W}SC4$Oxvzj5pD<~;+UkN^Pxy|nmJf1TLR+N_LwRQ+aNbZ2(nYd@L#N%t2h zBbLc&axri7GLOOz)thfW{CEU@qBJ{grl?%t;koK^(w?v;GblY zRx`_P^$oA$7QW0tX(|Wtcs#KcJ6cXU&}b}J)&z?6%0}U}3K#1akzv7GMaM?jW^|{* zOnba>M)p5QSCD%J``oX%TwmD_oqJG6k;5`d`BZ%OM=|n~rKMXKZ;KF1Nq@0r0V(XU z_5Uc!v!?BEN%YAZ$Ig46dvyVYb~WhQj!cbhV?L%R)`1b6D_X7{k|D}rI`_L=O(gsA z^Vnne`=ey*qDOCVKK={7p+?Zpz5~M=@37SG*M0Ig+@%)P{Zvv|O`iHc5yhYxIxzKw zyVvehn{aQ|ix`x3k>|UH)ear7 z`N9A>w(KZazYjAv#~aSqvf8%^`TPnK_6ikp!$WA>*YZ21S`W#ybrE&34TbA2wAO&Gbhg9q^GDhJIE#Q)l8(mUBY*@;Pid7aE$)+9Vh8W$@TliRua~;RfKg;PJk*4)>Vs(_Tvv@#sg#k9;)~kcYwGa1!P&6ZU&Lq&pkG}7DdtkJ*#Z`~xE(<8{nTo*^Sr{+{&!xKUQa zaCwz!+bBkJw0b%GGRO+FEdQ%qxL(alR2aapOj^`#zpFC&yS?*&{}RVabC6%R4RCpbXntTYq&wKfoLwSV9d@}ravcZ0L zDv^@_`YA{cux-BN$->Zp()+ z&Xx&{?~Np)YE~cxDDA4%M$YI|V{SK{V-r!dUEPCt;XUD|)i_Gn)gFICmY$fw#5ei|7t%R_l+F#+g*ADY~&+XH8c4 z_0{O*Zi(75sNV1(m)Of41i;B1gtK*}fE>9?#SYQ9cTvih`%=oE_{i)}vU(_U!T!S~uX91!>Sa7#)_3Xw z69v^@Ku}S$!oPY@NgrW-o~4OMD7_hg+8fVP^q-sxd_wt(wQ|dd0%^Nn*wO4Et&`!$dKUdY`p+48YUW>Uy%m)oa?FtsW>>!YkBqcZE!91;X7Y1b4vT$XCdk+|dLOAM5q zjXES3*D5#*mTuPVp#)}?_e2msoY^KIMz7q+VE2oDxm}K#pC(#|Z5hG<*8l<=Xkc8Dfig-*UU|Ir*p5N5VMKI6+{ZJbkUdCgd z_$``kWC3VHn)SRK!(0{`gmI!JJMGLtHu$EE*M`w3xAOYu(2B}Qb5~yQ(v6RWIL#sr zJbGp~OyQ69u8XmUs5VX0Wf)&u%KxomF0OMcVQdGs z2B=E|dH6pgYEqXPm*oJ-gZpdq3-qc<(~HqD(`sT{(XwtvuR9|UHl*gp(!*I`L5qgzOpN*>|4Cz z(w?zEpA1Yqfu4Ug7Zqaht|G(ra|6h1(sgDBV;$P>_v6cr9>wA$`ioVYd@*dE@#0Kj zto3k?N#Vo~{xdB1x0#hc5kx4HDzYY<>})gM@7H;P8NLFu@TD=zTCCw@t))mJ?rc{n zJ{46jve8dZIbJPBfnLb$u{E>c>K~MhfRdOKB|6pjuRW~lc0Mv9TrVuPz5{Z@i}J+l z5{c_DHEfshM@3qny;XYE^km!5TK!=BGC8|hFovX!zv#$0?gLti5C-BErwQXr&*09p z&#uFHX(LENtv*&SVHESgoM^ggQ&EW`FVsHA92g!IAqGu?5sm6))@wCA&L1a-?e>UP zoszlLblX&Wz-r3yaA|x9m#E{Gh`aut*PuK=a5k(1zQYnBC|!4Ti1J;a#nm86nQ~!q zQA!eW@tG<69p81e26}ZxYdl8STx8rih<37SV*UCdkAi##z}2mGya2i7+!mk3ow}|_ zCJxE1W5fmgWw01Ddk@_VU7Ek*#M@O7DUHFBJ9Jhor>^*_{!aZ*gZ zDza?7MG{PiwX&YHk_Gw%A6)WuQn7u&`LZ!H5^nhjF1!gQWj!!?Cq^p=1BS5%p&4e~PkGflt1w`9ZBH%~M z+EvlOD6wvyHhV=k0s5+rTRugjK+n$GyC>I8p0M*^9oX%ZoLq78eGQ9Jb}_#9+W(=X zmlrqCpL{xA)70tfb5hI20B!^?EWMXrYgCMMwk;ZavD(#NBIJ{zM7`0355#Oxbt)gO zEZWn%@h&(Hx_M_a{$-JC^3FOQzN@+1zP%!{E%$%Zm=OdPyFUyR)Z?aae7WDm&K3yiJhwBQ$X_~+ zB(usZL>+*Q3O9^V??FR>JG$fXNZoZxwOr(iY-tsxbuQ&=6ljEVy#%kte{(8llHem^ ztOU{}#*j{D?X7_|U=&^OnNh=qpb%~QthP6pa!46b7KS!To*1~$x7p!wvU+z#X8_v$Zj3L261v~RJdnhP)k0|KO7Vm041Jpi3q_H^~M z#os-1fi(;(0znmNYbo(Jq2WFUchIx#Tdx>JIeJR;zkjK?DuPKMPNzhRTSfp-d9zN% zf^gA`zBY01u+>TQ&EK95kPfj2s4Ub(*UcWOd(FZl`1kDG-wXf9cu4Wirs?GSI;4E) z@OMa&rHlAx$J|b8;H+whE8t!JyXgT~n|03&e_DS)Fm07-OxeUa*EhK_Rb^=uw=%3_;TQ4 z>M^+x4zh+hl)H>%6{r|F?yK19qWqZTSYQSkwd-;Fq}3<5`r-AQ{IT z2e}zwS!T!PuNx27s4%;r&+j~4?r_K1168OT@L)`8g@$J9k zz&Kcq&uhqQPp=$fyz{O3|crbn7{v{!+jNB?$I_QK3C>lXdcGuLrIlkz2S!&AL~B8($ahRW9`;A zy|GX0Gn?Sy3e4cE7PlYSU|=#{kGjGLbt75r_;K8@-?;C!UGHwTm3qJE6-jrBgV$!t zexf^z!1nY^ik_mWn9198pD)z*KfFIZNw?E%nP$Py48#A*XAmeQApzN#P!3I@J3D|W za8r6p+(M~rdk!4=^RXFyPU1nl2U%`+RgO`-K+BOk_u4`gl+vOVXaf0dq$L85N?7+R zBAP3UJgqzD`oNYpWb5^*V_CR+g|IkHyK13-%7^EmNC) zQ6Gz|J)|PhV&aAP`T{D>$7Ox-o*vpKG>ika3OMA z|Eng+%pxZA!KTFcbQ_6gY2P$(8**Clt8H$i-qOgeqc!q7ytXTO{V)3^Vctv!_m1wj zUEuiZiGl<4lE+>b(&!Vozue{|kF*K6nQBi}gC|U!M9a*banX{A%D)=XyX6>yDn3{C zG#eT`xy^tHe7>bao0YkRyB!kBn*t;Tk3j8x<9<;Ru`2@3*B-2067|1*9ATJ+MO=qf zRw+6g)XS5_PAwss?GY4)i8b8%OZ#c4jT#g-^P;cN#1sExaO6Zy+*zBNVmLMCc`UeRvDsQ{Sf=%$+z1vj=8M0{(S=5 z%GwMa?tcjtGT45Oc7|Vbue2c+tt`MVdZDK;KwU4V!BrEg8$*k$NK8giY@&vEDo?*T zuuh7Aon}37zy3twrR^TT^_enj<+s^76Pb|2SZ|C#ZEP(g_Ri1!{ zE0maApSTVytWqw{kb=EFT%YVFO-Eo=dZ;P*n9$1?T2^C1V?RHtm@&O5!9 z|A?D6-T^!2)uNLnfPbUp#`UE~J(Cg>-kZx}ay61UkD;HdZQZv9uBu7S1fs@}L>zcZ zt%o=7p2@`pWARA({nRGanm@X)@5l`@rHh|z8rKjIBK#$BS^ zA`lE8Z1bo02b;T#wq;JQ8|aku*Su4`nGNc%T9ruzg}{}lD`PT=gwLMixayj>2w5CG zZv$Jk8YK%Npy?z$(#Wp2wy5PUp@K}=AkRFr%}s-d#$#BrATT!|^M;4Fd^VbF)*{7$ z=~4>R=?FX6PGsxTzrB8=XGYCsksZNQbnj@@j0GZ7EX%L*0pk5ix)`l|8~JRMhN(-Y9vs3-^V z4D+=cHxdQSmAJd_$!pZ0ac!FiickEM@o3{$o^D zn3V8jxd{;!0i5mFX{vV(VMjUC#kl{yKT}z!d{@OcLQ-W_4%?Rc7VG6HlT#K?lsDhd zq29o0Z5&T*^ZNRMv~E;0b;H2#Zal}ob;${OD#VeG z#}CV8^(y!1CTUl4kUoyGe*KD@tmI;sn#h=alLwzf)BV-p{nQa$;teA7@dU9+tFB|ffh2t?Qzg-)K z>@N9`jq1-EcALGG&Ex*3s7q&@>QCuf^#X@+cTA;3)z4F-Z7afa)4|Elv$w4%8+>ol zY(r+_Mo{0_k=7(cpC!F;)1j=w*92RO@|a5Wbc#syeCA-=a*wKR_(fE!^hcgc9q?a1 z{fc<^e!x4mcPp5tC|+A7)VBqFZ^XiQCJqZ(PjfJoWO{ zLg2OIO#n)mZ6c!9ZPaQ)&o};44>0*GDUZ~|rMHL$%6-Z-%<4w3c8*1&C;jJg&;oWu zRAV89>AJj20FaDD@@cQ`mqVT+7V1ntp9)!7E}kk?&oq+F*BP9O!iGGH&XvYDx7`&b z+>&p2Oj{P+b>5kZ%gf7)ioX7YrplH)!1KDK$ht?4L%uc{0^h z8PSgJ>^DZ59db-e!X@Q=h!FcnjYQH1stZvA3Ct&IFFy3feQ=H2i6=*~<7UlTq- z`~o*Ux7+AhG=-Ad4{u6*{*vzF0U1d>HaP_PF0mrS-0W0x`J#X69cv)bH9&8!kJH;R zNW=8jV$XovXr*i7vrkpiP5O4V1Z1`*aeFso3@H(egi77(p2^O5ayoZQTJ0t7Zc^e_ zDn#x&n-2vz#c|3LOF#_#zGy!0-E9c3EYAv;6B#b+9hB}pDK>HUt}x?h#(kvjMvU=l zZCUfF(te7mFiwn|*^Sv`;}PKnaQB;-eeVv7IKDTn-(sO#EgV&hfaRN!W%(yiA-6TB@;)^ zjhi{cw@-2G&q@__&Jco|tY+zgi+P?jZsg1}D%wyyoK*eamdJVcF}6= zbe0~Y2yt7>y#r$!!6@tcsag{q8-#O#S$c$*wN6#-2V`X%GVfMp~wjS*(Enovz zss&Ch`=X+S?alt9%0{4xOE6_!l``KCscL&~Qo4 zD>2BybO2nxER6CX0$DtVB~rP%jxGu18?w&WKe{M<6|*^;g$+{CSe3*+0Y5R26V|g& zx=E>-LnrBNS(!sEd5k17YoWZ}Ik8KZnUPE;8*vftnWB5-Y@?poeJZX&@ zV#?KuJ(c77Z$SA|2E{|5TOTEAh{V&AQarBwZupA(P=7jDa_q1eUDwCJxa7ZAR$cHF z*Qd_*_>igQz+5IW%YJ2dgX`n{kgfpdyfSMey{TN#LJ9>uqvf^*%8Gj$-5=-t#xLqt z;P;YG3#x9tgQ{Cb2(Lzchveu2VQBQ7=Hh?^_}v@>N!DGL60t4BQ8sI~+1hLiAFJP0 zWFE{fiQme!GIKu&JPkfFlc+rAs}FZD=ov4ErMq=b$STq>o!o0y86m^pDP&llBuJp( z?Gdi-o{YXSb6_8)+Abv9iis0L>&dik|O@FMyeQ9cF5#0 z_Azt51;jD4|0|g)Zm>EY=0@_Fs*h)mnzSqbDt!n*`m(FMT``8}m9?&Icw!THT5%W? z#*NS=-SGI{8d~E=5)IQtkw2tqW|i(yi+AGOw--<*fae(zF&U`^Ojcc-3`;J-uLm+I zDoKp@$2%o~99eg==+^I1Sr2(In9bFXA0Nfs%%@@~BBN-c_G;{bpzJa?%tk_elHil2 z+fL>PfBwt1qMfr2FHR0}6}5YS z*%<}T%WmzeKghr(ZCX_+CbwlX(6+t7U&MmZNV*iP)h_g`HA>aTFWcL~2fw|%44+)2 zoPf%~L{NA@>o0jCXHaR$jm6}?s&K7aE9c*Zu>p^~c2BK6f!5OgUD@yOW{YiE-Ko=* z?foG+I_Y+Q13vj#n?`$rZoX*t-IH0z1-6dYwAjX#8103Hp6Hzp`>W{Ja9vTQxt zd9-KCQ;7#_g!Jhd?!n^qay&03(d1ltb-No;S z=jJPEZd*Kwp!T;l6n2~r2;z-#b?;n389ixB@=_?>-Lr%jEqkaqcnml8@UfbO36+50 z>(R3Xqp^Tj2D>HH4{tH39(T~lixFRC+@1wDZOWBvm=6yUJ>FFH+y z0Efk2au^=@S*1ohP?fp7;=Cj2+sEy`b1#(4l>y;rKgw*$D4Q-anbr215=)Q(-KeMo z@^c%GymQN{UBz5kPi|5S2a%g1xag&8TUhvrS^*-lGm<12r2-yI)niEMI54)f`nqt$ECesTTsBv$6E2tDZg&=WaH8>$+Wn zt0Vzj&EN+?j&fEtq_~~ElYz}t!Mfz$ZNe=AllU4!H#tFTs%7sd>^;`ZLz4K1r+cd` zly#0&-6eR;k|A#pV5gBa4M>W*AmX05Ur9Ke{cDag6HS{R(Pl$;75*0l;1+L8$ZSfw z*HlR-2ML!SSDK?WH_%DDtVZ3M#GXlnd*#NUjah*@pcCtT9N~JJ5E;u8HEfXx=%|mj ziHu{tZY9vGm(HNh7+$ugi67z?7!d%irz{}3;i<) z#E=XPOINYHT;)DF_-}sc8z=>^>quHsO7UzGT^$~mqV%siVx25+xAO(j3&CnfPmd&6 z(H)hcs`8{1@5+QM`JFjp2%fK6p9F)^Z6!{#bZ}!1vEXBk&+p+%D?ytjtl`Q!lNo)L zMXP>E_BJ$C79_6PyL^KOkvB_%mTw-HwV5*o8i@x-`1#vP$J%AodLWyn^De@0dC`-U z(Kb4dclaMTF!ds?D9?bq3k=@)F2NHtx1AShOkWWA(+%DhctrPn(U*}RDOd4%sWU^< zo!c*0z7XH4iB;y1+?q3C{gb~A8T$j2nFVV{S2WTW*@J(x!+xdXa1gZTnX9F9Yb$a= zH#e3e^p};;KIZ-aj@rvjM$7bZ3O{v`<((q6dcvVkx+j=UIKj($M@_47N4$1gy{S&- zxT(rbnY8>0?Z}omw_#Q-=V=nVm3Se+!-<^2DnD^_ao3u|Ij8tysE-JDv1AZJ`gvfw zj-jz~NyBlL;wS2GI2*0dN12UsKGuEPc~@R$BNv^sGNpZgLWn|mCXq+IzP4zkBw_fr zQ)mxm0UIL0dZ=%#Wcs)v-DU^`%!&})F2C0J*{w(WByL3wI71uic0+^B z9WeU9ryG3=nPj!7WKxtvB$S(gDs0q1W0W&2L#=MDz}0X<<&vDAIuM7>&xs`tjKt9e zut4neiMZK)ET)qyfsgxGywyI0Wm~;AN8PTC7o9Gj)SVQ3G$zEl#v1}Q+UmfVJiOj{ zjXUvyo@vy}2NQpU=ifkyG2tiVgE(U@hE9Yx12y!2k;T8_x_<EB;T17j| zIdw_?woZGRLO)WLj^})oPrdnJyDqjiGe>!%Y;xo1$Pz6R;8O|C#>}^{Or3xa#V+!& zFv~xffdowsg3#qK#fI&yuz9BqmSA>~aRV>+%?hZKTkIM+Gf5ILEqkA%2$1^Z&>q7df%9HduhMkV%k=$&eg|#<`HTl}#wrcA z-@}mnCa1ywEtC$(u;XnXrMd@0IX=jRsi1Pf@?RzQm<5pBQn)SrS``rGUBF0f&NqUn=3D;G z=IDf#tXBRb`N=^6BSYG9E$J=@BA2kDN;=)&==~~HL}dZnv7nQMU7pp`mg=~9++BF9 zVLCpK#jb_4`>-yd$wpRA!H2}qx1%|99zu{dLm+~>U;*#+Ana7xm;9lLD@Ed**tI$NS0xVui7Ph6(@CIPB96P|zd zBdS>ip~83LP}B!nA)VVFqsu$SNiNm)rxf;cW3TOCg<}?c$3L}(-Z_#&U8fEq(RRgKrR)k2}HCI|7mgDGocwSbhAi^7jw5W*C z$qVxdCRYj-^q{(9MLO(|a!-F{wyza16TR|QyAq}YolA(|4QVBLStN*DF7$MGBVeHb z5hIT#1mb-Pq+fLjzS=?!ezcQlB6@Oe0OTBs;p`6(Ub+sfoknO)Wzmt_{ZH{)5!N)z zPnT`sDPdFV-*3g-H%KLUEfP57Gti8^M-Q&ajlIG9Fh(@xZ|vIws5X~P%(&Lbd6oQM zaSt%H#t_fE+=!xy9A)cubn(MEN-vL2RYXa@ ztdIC(ZH0C!3OM=E&|1{Pa5LhxmhxCRG1a3o!zX>v#`LA=oLtUI+0RkLMuWIb39MMc z1ZUWCqNBrEIfQ~h#a!RGh36&Ly&8@jNOy{}_MYfXau}Ro6Fp&w3C25+!4wL6>ITB7 zSFAJ}up3EpbXVFqf)LBUXQt!7V_~gXm%p4b^!N|#5=n%%nWYli4RnmMDGb0&{w*TP zfVufNFANhdu5?%(Xcp5roE&Nau~Dka#v4nXbG$!ENn8NXbc&+WL8FfivM z`l5c2aOj4|Y{XDM%WMWn!eANhkz83qwD3H@IWE-R28GgyLWlstL=syFc!9Mfv~oE6 zbO1*XSu6_!2@+gr#lIJX+<7!GkDK#3{jSLydDp3MBNx%_bnyMNcR5@aT51Rgsy|I| z;nDj{xdXB8qFVER+m03WGsIfc-U%j%<1o_0X|A8!AD1G8a& zs9q7F2~L;#un7^t?+)4szOn9H&-G^!W0UW~GqrK!A7D=gLG?ZtUM^qIehPSBqTMc+ zDO$f=os{=25a6;TFzC_><~-ULsnjx3EjJT8f}yT06z3L=smgd37|kFah<2szONGs& zAvjLECkOH=n`~B`<6n1y8)w7)D*4;lcI<@sYD?3>e4X_Y7n*l40(i(bDWkzLh+U6# z@D5D$)6o1^d}wHgFGUO-Y~Ggr9_EXIBlp`%Js!JlBp5PjIEVGbWH*cA@)=)BNF$VuiPFA z@XDKz*&{?44Tc??B=aR$1LC-tx2l}DExokZ*dqi1ZyJe?GXUfAop&(6H%Z%Xdk<-6 zFO$yd7@8F-AfB4N-PT4q_uA!Qr+;!HHwRy0O#eQf`bmnKc4DP}ek*^K@?MOq$N1BqG*Q`~l`>XW_<8FmjMo_KKLyT0n zqHS3Le`_9WofqQiDRC6yY2KA|WZ`5DL?j!ZFYk5DQeDnk~0T zdfzt2wY;H=^yL`|TDD z4t!0QL6^XEH83&mCmZPbLSy@co(}67;wQcSS7~#+iTRX=@2TJlJI8?7uatA+@?ob4 z`k3d=1?JMlhGwiiYs|;-7pkT6NaII*J8GiRUiCTY7tjhcbKC&J&@079{FBmc&a@#S zqr+&3v9}bR)#OPM+=hgT;Cx;)=-q0Noss@F%BfM2=CvUbkyUSzXLu7QKfAwA`8B*X zE3IU}%=zYIc{ZI%B!d5lG{iY?B8OH`enVPk8v*t(bZ?K;^*cSeOVh6EAw_&<$GIJy zgA$=)sgz9T(;NyAxqH%mspMvK8ceyCG5~Om47oDnWlz%NDR{Q4H z6>0BN_$1-0pHDth)!L7|gd#2PheyCozHfpAVuQq1%6bG6+*Ul0$R~&-;F@gGW5!(W z@D|GF+sHRpRqO~)GT(PFW+@vE8_Uif1i{VMt=fD;9d_NyVJ%-03fRn2nQ|c?U@=wd z1dr%Yc6@nnGrk1nPS|;zl?J5P^@n>hO79-oi5~H|#(2!T9GDCeEpL!n3(><>_et05 zLGb$Yv6gt$VBD_xveo!O8NwQHeWHW$h97(9x)y%lvjSmye6&tq*#tdBJVgs^y&$?KMFAZu&aEwWHUM+&aPL;kRr3HJ;;yhp_QHe4?BgpHM3M;h5r3ts5hDz;BUPQ9+1u zbG6T>VS0T$0C@G#T@NC0AoC5OjF#hhPEu3l7w$Ri;-U{If27@cIpl&$bnDKo3l-^z zU7Agw`HS&@luAfiJmXJWphiaY=(#2NOq-L^w|Sz4i|~ zSh-&h++G{cjCrxPF_hoaiwkWmfKfz91L9lUM{Uo%tODc@jA+&xhzt$5LcdNTb1JBk zMP{~bQndhw@DUK;pT;I=h!}O>c}^Z-6Ww6aA@ZqqiQ`*C_$65PWIZao0T9M#TAE>b zIWfhwAuw6v-+Yw*Ec}JWsTjbfLk-UVCVn@3QYZo)k`C|kYs>T8jzoWa{-Ook?0^qZ z)?&DO(kdsU(AX>_Bw9w_KLjKuWW!k6D3aS>IfBTehgfKUio|raqL#vK<~BTE`BSWIbw4_HnY$M z(B=y5yY_2rMw=*?&yVHA4q$}C<$=V&7&E;{SDG0a-#+WjStD|QAkuil=MW@g+4`B^ z?52FSAO_vD!o>32_vlN2w&+7im;3=edt|ITR5{)j-*-*eelwVV^)pfxGWtz&rP@;K zd5L~Ezbme@+QO>6Ew}{UM&LQ(`AF&S6HryTp0NQ_)z{CljCeZ`T|<+_hxX|!Sabx& z3avqh2mX3ffRk`h-(5Agj#m6uO6cajBxVle7IWwh?IbF5m6K@sLxU(G#3uddD5hhu z98Cb6?Lav>CLMcINMkBj;^08K$2ks!YW)r&MwTCXg3`}~YPpN$m}cdcA|T`59_=)EUyfr{S=gy|dyaEkF)7H{JH1 zWQqX$biJMR6X5nTP+*?O$f38dRL#oBAv!zAg2a9O-mli?tc%ucBoZZW=jCR|>X`&a ziF(dMLhI9yk1L;tgRfbao;Q$eUK{bskP269OYx3q=~xP)KqEZcpbE@&CnwX>eLh}! zjK|I~Un`DtNvt&!y!{|>M${DRexo&-`n&G6#n3Pa!D0bp77-G-u?GL~& zb5-G)B5^)4>l)Z=XM&$TH4_*);zL5ZU5msc@lZhCMq?M&^8g`0_ow z;S{;S=S*Uqw9G`-X?x(fY@c%RmwIn5C&`HMKZO ziMEzZ<0Ip5C;m&AtrTx(E11)>u2a-$$5}7Y_c!)|!m&kmrCzWQ>(Owyj`%}!y|~tg zo4ZbQeftc_wn}mPaE9B*ps9zvPqmh#T@BqQU1@l*2)D85f~x}Q{hhO)uL{Sx>evLj z(2HHL%C8TBM0%t7_0>qICM~`qRklqI_V+XOOchZIezXMKoLsk9+C?g}Qz}5*T+cU1 z+?jhaQWsH9#d2jvPl&8l&1H3tJ{T!}u6G+Bz~vj4=_z5&4KMNhi~y1frU!YplWZ&j zMiGg0Z4opyZDDk3pD-}-6+UVdv5j3zcVVA${~-X|*zi^1oOyQ0z51=vd^soLY%UGIZ=*Y2^lBfvoez6 zurPqGt1Tf*=tX#>ljTH!Lg27@tI7s=N4_wzr#a2oFqV*`mRtKph?MAAmZ=Zj(gXB( zoKbVy=J;sD@`aITE2}ysLj)Pivkovv+Hn~2%`ycgV%GQV)cmFpiA@CHK}~mgB;yMd z8zsAq(&i3OL+B3ykBV?6kjKP4>%?p7$PI)GAAeW8HHr_xji99GZdiC{dul=vNT!@X z%?k@wy>t6bMqKlKO|AqFBsXbh=54%y*KGq2!xLG7HR?^Ft7KUJ8QnX?%Xwt1uMyq{NS8-pZ&Cb&dY6R*rwIq z?X3g+Z*fp`N6fa>p^fI)p%slEQ0#_^#(Gb-1mj2fB@Tj5WMQv6qTqI2Un0VnhGINj z0K;}h4qTX5{+Av7+!co2N!5OeC2#Yo2Tv5Emk4G$3ieLB+uS%JVjQKs`n{~Eg;s7R zi@RhscsJ0-dr)zX^Vo1?fL^ST!L0my`ftK<2=U3`TO!5v?x2s-r-pOi6Q@a`C@=-} zLlx$UDhW;a7E^Sxq{1QG_Uhc(&PCV-9<>{$_4IIE6!~uDpCj-YDG881y`&}jPeqt{ zdw-us9H+D=;xhCx1KQl&f{*=-(Fs$Id`p!7RhU*3#(}9?C?Z#Oa50Yl@A}gFt8_zi zsrQnao-qB3<1@V&l^9AUtHpUeOqwr4-`;t{6CQUhMt+h!V8f!v^OYZDsw5hAKix`4 zA%H0VvEwqIr&Aj>z_sI z_b2-9a`o2Jx_rXNzF6yGm9-^+iNF<;0m4(hej5$cb%d|aI=@ur-%@3hfdlx(S4!Oh z9kWgT8S%nP9lLI?xLd#3Bh=becz#ekO6R-dyHiu#`l5X9BbU4djm9(ykuNPL*Yxto z@3^nY(^XcuT|QayCnKO{9hph{Y#k7(L!=mDnQfsCf>%e|!w$cXGzDIWTlcMvzz#oW zAAiPf@4lk1bex%rOZ-{!Pbo3r1`5eF=kI^JHNg9Pg$x^fJ)reL+mnzdn3}Fe&9E6o zFJP;CPI}!Z48JFy@7`~?q$>8xGMLz`YK|$$HE$xxxM+UR&2{Z~QX6bi<3i#j zh|#|a&Hp~lzA}@{dg}IRjQ^jy|IZ84gtvt^Jb%B;wjapz@)wK*)FX_2OUfO?rS?7e z;hiP*$1L{s-yO=1B`gE7z#czznPX(kZkOvCCi(VPno+PdR)fjmKX5?C!^LiJk0nkv zp9KlPLzHJ^8)E04{k#&1{B3)D`<^8SQ#-yynTff#%ub_xRmlJ})iR#p!Y&t(1*6sLA9^)BCvjyco2~ zR_gIeU3OjK24jp~tp`=Ol7NP$X{k;(-*6}~aSfIXMowzD?&R~fm0Askf&vfY7S?Uj z;iVh1ziq%ouZ32s0VndM#Dh}}F_3-jFs-)Z#+!c-#MphHEXmxDi}(kI#qfxuJ$G2- zZPn0Dimi^A+T1Q;wMvX{$&`--{??}qim0nJ#}q+nij~Nha6zvBY&ZTT=KbqI_`BM+ zPM2W#b5J~8< zF7M*3rh;q-k){2iC8{~i@R8i^7wk`$1OWS+jioP?4-@`UJhxPX*ke`>N!2t$!CPh7 zsWJf>Ho_aXGo6gJxHix@i63o-01+EErSl{7n+4KE{#GsExY5ly`QE*z!U0g17mTX+${GcoV^Y-jWeZIgQ2IXgXT2@7p%vl@pVu4)gW+jr- z4OVXG#z6DS#b=9rlZxoBuEfxU1%nDr6nI?i^>}L$R#y7=+XRNsZA??&O?_LChjv$U zVwi74r%EdLZ#kXcdPO)emr-z^+n_>SILIILN$D{G&xnCA-QShDAHxs4;UtW_f&R01 z6|PDf^K@ZvWYYDDq{soo?J3IA9pCYxplzxGz0>t}0ce|W^Sl3L!~d7JGfBNK^nEbbIMr}&Xo$H} zE1mI4BrE;t5!ZEDr&mnljrEfCwQvmwobt)2@+D{N zP;e_Pfu!sx&s~WYXIIX?8k=>Hhp*7r5PWF&S5EU3s zyuC1AJimj9#c^@-7y5~+E6tJjDtRZqZ^A7VH<&R5 zePlZ`L|_VR6n3xEqTdkEs(r!S2kG5%oHElUmx8NXgqAEZ?ypvma*n@r<^M8y~dQ_nSHC#?|<9ruclXTx8#@>-~I7V zfswl<-Y)7&%`7j!HFfd^-3YgrORmVCoF#LARW1kZ`1dLLuV&_YQ1mV5wc)PNT;#wT z8MHO#*3uqfr094Xef>e1aL6FJ~dTWKSYk2 zS^9^<`w9!(7%wjLw^+l_!yQFt*sQ(iRW)uyCrZ_rxxk#46Vp2wv>3bJRC409ROREy zfXeZ%-MX^pdSrCmD+7?;SijDSVpR%77h!4bI?ru~ETOx<2*%tk3*}UE&t%So#DqZ+ zTn$Y>O=W^h=ySr_R#UH^f^Ij2fo5FvH)#1xqvFh&VvT7b$B#4|lE1v)^igt2txvU> zOFVeDWc6Df9>|Drboa8!;q`nV}!fCJr3(#!!0ao1Hu~Jj5y&JoFf= zrQiatlnGc|PaKl|_M5%Z1z7$f1Df=1_K2Q3K7N+l|o}7f64)n`Igq+;{&Ru!AXB zj-!d>xSt95V%3)d@r|})|cBE;3%r-hFEvt#|3elV0NrPhpalBSa z2@X74>1}-pzDUNl`R#&)C=M&Wv$69T_8|N!*OSP`#S&r*4JM)!@usMv481-N3%Zr4{R+Jbc0uw;_TXQMog~N?rg)1&z&!R9F+4+j3s6Chy>?2 z;=_#pN8kRRFbl^k?sE!FtakafJ=Q3fZ@lMkSmkTQ>^N~nKszOw&&?u-k#D=0np09b z)qi#~F6G4B2kPV9;rOfz^pL~1Z!e>y#L0UnS+LbD0`=9$68R_|xG{TjhmoySqmp!R zwxO;Ke+L<&yClHxiJLp#>`Pg&;gpfnRCK5$UY(4_4sFYY&D41%z^bw&Hu3sxA-SV% zJEn@QBZ8b-i`wZf-ptAfz5B6)%5oPxTQj4n==S!M20zcxq;zve*+Nrz-Hj;PI9i21 zc^b{wlyv{Kol4C+3_c>oaovAdkXF%hE~g97p^vu~I;?b%HYmf7b}zMp+GBWE(ixuU ze4cKV7HY}Kb6Nb}r32<;_uQiF*4B#uE!C29TX5QM5_mA|fBlRQsGYwzKh|a}aH6Gr z_-kmw6Ye`1jRX3SB;-`_N=Z0-J(Y7 zb@b@^ldeRmTzvzAxO6>WQk0+k>&v@iNsjo{sEhs*i;ikrH|>uSy3L!=C0L1;Lcoyf z-f1~PI9M5043I~{F0X#wQUOzp&%+B+)|g}NK^PtGGTwVG{qt)dt5R=hL^lxJ_}oat zvi!s7Hf)iK2^8S43aI@w_C0nH)v0bujHic7c&rMLn=Ot$I)u?Q=o~}Yx#G6Ztug%c z{@O}V$LgJ~Im#x);U4zzd<1f4_zOXJ7BrSRa$%ck5yPo*vR*a^R+AQyyXCmeXP5Kc zX@rkcjdlZ8DQ*uI{$e05o%UE`k;~4UM>JVc@D-v%v8|1YQ;fx<%m(0O%a}Ar{~Eo5 zJo$hQ#xn#HlmSrKLB%rhf4dqUao2L9Z(2anbg`q>D6WIELP;e1#br;;$aXQdsk!U2 z`BgBL$NybZ|9|+Hub3O3-8PI8ZKWiXn*MYbpXIKk$qHzu-LU2e{4mqpC^hY|bhPXt zv0zQyNQ#>Y_|ZJTuZnW_9U&5FAb01`;H`OG=xj1m7=W-t>zryEACL6qu9_$EWe6ML zoegXJDOD0SgSRQzV^RX6k3b=+yC)6&zsFXQ?1ZDuq^%e4zK0=q>-lR~xPmQl$v!rw z*TZNb^1?o68O8fGHoa~N+wXc?fs5!`%c!_0#Y6+Mg;DOmGSn~k%_`SLje0D5B+*=x z{?N#1ltD46^yz9)3Vx^QXad@mhbh$*>iP7`xpQ+ip3jGS-7a~1TGDRihPtK7i+4IE z3N%~_0_vY1(y6~#RMFK|Gf+5OTZ*e#WHxTHel9;o*R?NzH%QSJNu6>vGw>h&691Uq zbi^{~S)FU|Jq{XfthNUyx>qm#Uil-)E+kmLqLgBSDsEn>zO!^Xc}68x#?eoX z(S~@1R^+|NE`0nDSos}w?x)yESRQ(!oNn58kb+*{Uys&9JSP=CR+4`2moDJ_dG>Ww>x;m*O_4@j*R%T+{bETgxb%OsVEXwvXV9jTbg86Vm-xMGN~ z%uFzYpvPPzv9-HWgS^uh(aoa){y7KIgn51AjZsvX)LmE8eIy7 zw~{^OleDm5J!78Q7vusFz978WYHv}{=&Xd#>|9_s?c+>$Zxv-R1c;P&e)gEY18ps5 z=^hZ0I1oljD~tymTRCabLDPXrUulYFTH_yNa)1Lif!w?UFnCpF8$2ib%EI!^-Zpf&zA(#n&CDpHJ8L9;0uBi=z8C8T>Aq zO9FSbnrtiTUfh{nK6{{5i;6ZeFyn^Ct3zqUe@-j zgg!PTr@Z}fA5I*z=kS5QSELMA!IY@9oHV2WSDet-DAm3H^U2@MO???qUw5TtJh3g6 z!PN_#SL9YQIUwAs&?s34+ZeEiSv37bZ-z>SaGsXpm_ObSs{&0mTn%8(`!g)b32TN# zKkyrS|3LW-W6!V-TNh>oSvfWg3IHh2Hz@{> zhf%YAI{T)*ZoXsf(B_ch!Elz5Z#&rt*FZN~x#?EXR=s?ugXEof`xgX-yp5Ij{Y5oN z3rr~)rhRr(?|-WHwUd`UoWC$?`XCIn1F z1MNNa5Q(+_QV>yL-3OLscf}8j&>=s5mst9tpx%1p+xAoq@3hgksB+^rIfLSrF8y1PhK$I zas1C&0C%F4Qdg!N^?2cOcM|Iy>&IhNJj+Zf1{TRq95u8pV~szNq3Yd!G6@Qoj`--_ zd>HpYm9LgN{7Sblrpl2PbhaZ`kR8TRTHN-Vq%P_AZrJZ0@f?f40H(TV8F)f%yM0ph z8tz%nq;|!DW;p=({_VHYlSob`+ERk6tWoUzxE7o7`YmR~me@XRuyVfd-U$}KLRnMg zIoEf+s>7>Wc6PT%Exaya2=+W~!JNgokE8?*+$|V|Y<|gOjsk``#54W`F>Nh;`hW{_e|39E+wsI}9}V&qD|6KIcesikEEV&S!3-mpM(28O zX^cuG7Bz^#yaO_1DGFBFJA4&;3{{eD#>fIr&TdckE<%Uw(B73}1YmA8k=rA@^e+V)a7r-mxM(E4v?(h#X;;Hn-qo@zZ3-10{Z{vOss4m4JT1WAoG(}o7O5W zbLMe@roV{TNe^UiV$31GF#y}KBu(;a^YcphKGSZn?PU$e5>3!FYXn>p9lBh{g{`6xu`^>|x=E^C*u!t5Il`=lJ_fhmNmP56 zG7!+xzq0wViJei|-6@4Gpt_A_JoHFL_LxRBO&$_i`IPnP$1BEOHLW# z6YI-xbsh80yLP20iD=wHwGro7P84c+^r`mhiw|ne;g1(xC%P6M{y1zbU;4ARo&-nh z$H@K}S_=J|Hjz^O${6v%k#Z!43v*Ike6TmUswB>ARSxT~w)5SXpL?H^ec5DV4GD(n z#q6!CD!ZG$p#YdY+H1I37nrwm#|JF-SR~6TzH+%ey@M95`hM?O`Cq+H9ItIW|Nc8F)|A6;8Rv9gOAbx8@tEhN;sFhC$oH zLJ^f5JF^XbZ7cmIt-WGR?CA(!b?@^~Cf6dtUgs@z$wGBaS6J>bD~Ghdw`HZr!AkLB zN5Vo$7bhrhBEQ?UAkV)wWKTAx26~2f$#9x$gdQY{Ku<=jpbPXmVWw9QQ5l7CJy&Hd zn%_Eam2`!)Ip;@lrm@>AdTvqYy)2@QKq2l4o1JNE&3yw1;*)PKI&)X0K397QD%-jt^`s}V@vZ59z- z6oy0zk%0>xNr{Apj8Caju+I3T+8%J`gzG>&DTBl9@J#Mvv)6^NOr{33@z4KGp!%nr z06MNSxXSmw)WCx!fzZdG zIoRGrD69Z7<~fZnf!lkZoh!C=uhxs!oG6QYdRqr5DT^EtZ<6C;Rxw6Jp;b`7_XQ+w zT~T=4%xN#9x_-HxeVUvLKPbmrR88`;{Pxh$#LkIH*?#E5I?&Ap1HP7=afRjOKP(1{ zV)gI}PvAt=OqG>l_nGd70yIHrC}`RU{uDmKTS7qzM$@d}s>-;bPVZ|qrvTGUnPcXh%&)Oi{JMKXF?9KwasMyJ^=(+VGED$mis#OP$k=ao zjZ?msE;>ov?o3iW?Q%-&LCwVL-*fU@zAL%V=AjJehQcyj0Wx?dbFz}H}3U~-JIo&#dX^jq;%Gh1rQW>lsD+{CPd>Fp%4;dGv zJr0pC&!n!1;pzo)HVFUIRxT$qa5U~<$yedbjY+;T%lpFn;d>1ur7&EC$Ce*k`KYB2 z8-92oIJgg!b+iuH0I|oBZGq1X^#`VU8z6tSUY3RqbYbBerz!oyn3mN#Qz!*W$N!9X z;e*gD!@14gVlk7+LWXp~^>C#C?3lZ75}nT$6S?p(g{!Rty|Opowh%~BShI?c%RI5b z_~yCS`iOv#?MFs39lvV6^hY1S*T!DRBOtwp0drfE3rI-4>{&0dzA zqGG~~3t=gT}S?FG0KAyd2^jP1G- zZoP}xMG1sIDbWr9V9L~0cN`g)LpWkzfk`l8uF)!v=;EQfPUS@(4b6Ol%$2g?Z@AgZ zC}@(h${z}`<#25uCJ7XN+)8nS>e{0Vjs zQe2Ivu$uv!xnl$yWxL~iL%@M-RFw0A_y6f<0{}*x4Lc{$?57ipw;PM+3o)&UQJcNb zKHq=Wjsg@SO8V@6wXJkB?0v(E{S$Gb8YZZNQ%uzFo)V$`T`9`xu#D|Ur#MZB9K^vm z-gsu|z1UJ$f6uOIWl?TYn}gJN`=Qid{%GgSZ3`JpxU$7u3hftyek5WKb5|Q0pGQiQ z#C`wWg1}cf3c#z6e-mmZV=$nQ@OP6P%v2D1^wh=2UYnxHh`6rrT z!D*K^9pRdyb?~I^P_&^Oy?^n+0Dud=vHaPj1>1U;YD^Y#VA_=BR_Ai>njbO<)hW#k zp;OVpo8xvkyKHaSh%H3>YgMkTKf#ZzvDUee;HA#Xt({05cv?=ZRe9@|B(u zkL3*5J6U+|W*(;|*Kqh0Ka+H!T>9)KSuJN!JQ-K&9VHXAbw3}YIWWJ#ZjhBKCt8L$ zq{=3j-F|OMJbE|9XHk`f@WW_rmCzU^Vb`{IC&C`zBAclHMEMQFRDy5+U^&i%pI|*0 z$w+=zuT&t6*{-C%!O3P42Gz6034s z$4nhabkgq}u>eCD1!~e1FyqeO;B9Tg&C)p*r&%U$Rq$O->LYz?c-PetySqo?w-KzZ zzem7f85G7UEBy(NnTGjtn*x`jpeGL~5?-T8ep&KF!=D&mPA2Q(KK>zozHl5tmBi_$ z`C0Dbtk`aJg%MVsbr9BT#&y2GaY0W`&Hhobj}b$%Ds^!<`7>ND0T`l$JBLsOUU;FX z;{;!xT)7H6N+=>WVdGF|`5R{+*Y-OG17$U}iaFw+<6|z)xG?;7_K&@` zzz2Ixr@hX59YqDUOhQied)e3%G5>DQ@H@o2s`;uH^TDbibF=tf>E}kr2}Ni2`1Qd; zjZ?SP0ZQ}p#nsl283l0$Yt9!$P)N)x;>)ctF8^K3!cg0^w*F4_`Sfa2yz^}~)hOO* zdEr+FX--c@^l+!Bx$BMCj-u}y+)ArkWvznXy*=?U&z^3R;*Ky50v%aW}n*= zN^tVp_qF?%Ppc|Oq4u}`EmZ#70AXu$Icu}CdIuwTR4W-PJK#N&(p!dxK}xHJVl8Ez z3{!r6WDa>9VHLqiC8k6$n2e^`a&VhwSq*_w#ArK4nq!fe)<&XVuJ%SyFgbEm)L+Gw z_r$cRaU6lIwR+co!%dqyE}M%n-Q2SKo{orSY(O@r*{MV?W02lGwuyXNHjz)rgYVsc zg-IRAxkc##4V}n9aoWRUjN>D(vyB|-?)*B@GRIy`sna=6ZfzErpRWV?JT6!Fm2W{$wA=2x{dY@x?Ev##bStv()BkQJ;I zrqY2N-xtE&$m|MR(t!*j>OC@v?>C)H)^Eu#*K5Q+sz>frPYz71Jc6*sq)7Mg&?lo( zFJjIXUVOk5fRE04Te<6;b{kC`e@)Ni@{R}eoD_kAk?ahd4XekmzJ<++ zou7^xWsCedm_5xF-)^r7cR&)WFQP86p^UyBz5+q&NOsmvEifOzjMQNFsd{T?c>azz zv!ge608Kl+tGu8ycTtGlrD7t-;A!3LMLkC$=X>pi%6Qe9<)%#k^)F_r-~G7rea^zM-4I`m z&tv5ggHJIHtEi$n(a5rP_CLFP>dFDmvpjF?1W^JLdS6$D3+7zU$PZ2qU@;YB@lHr5 zbSCGr@-D*0`+_j1um6LXsD2i6ffrlooSThbH^0+D5l#>5j2t*Tx)yoV0z%wYvJN*i zvdSm^JoRcknuEFzd^U19-<~^{^4}#~q-0fcM3aXU1uSboMdMT?MMiIeActzzrkI)jLQ1bm;?8ixF|tlYJ;?ancF`P_hL*Z zzqc2}!0sL$Gw#6sUs5YJor=X5_p9f>X~h017`*6(gh~ziYGsQs)Ol@Rvq=wlPzV~j zNvaMQ37-l4x+d>IH5oCoolAZ%G9qMo-BNYYN>Bv zi$Mi*C8q2}C$qTT^P@L_8g0f`wscqt9Gy~5jb~BM2a|Wc%m4GAg?w#~BAER$0ODA4QIsk%wGftb}8l0|3FX*Z}Y+EXz}( zM32R?Dc)mE*R8eq6Kv}xuGq!tDh6IJBV=A25fY(i8dDzeo_7m`P3Sr9XKSNRe6`sd zZez;8x;=44DB-1<;TtB%o?O#)AmBUd-BKn6@GcV3*~|^N*Zszk__Oy zl zGpjverj2`Gu57xHNHAMH6Pr_SMLs_*l-5k_K4(Z1sLw+`apxH`RngJmI7S=pu-pJ{4Ufr zz@NpfeD7bri7@nP*wYcBhcguelFgm^>a%3*R;%iW=7zxLD0-;gFQ&l@SW~!==Wa(3 zX@4D_9ld&RX+&k>%e<83e!KW?K@yT&F)?x4GiUoOu2JgM=?_ztd#+n#8u4szF0vg4 zl{m%qUrlhxc=|JgUGq&0OD8D+FQsD}vZaL~QH4Z97b|CsJ8Z{{-} z+GzQi>jUww!#gk<)9J$3swM)Dz>7Wfr%kM#mc2A!dDvQox^oHN-*yHTn?JS zzaWgR$c%4>NwxExEDBJ9kHaWPWG5aN((u;M9b0wvkA4g(OxDB$%Q14Vib5IC@S4RUl>)L>B&k}{q zhwoIgGxe1Y`eLy=xU*dNP0VQoU;p{uXdu%-)4Y+) zt(WRj7&WE$r%h9q(^PPHfrdA+d(FX{?!xCdIWCWCLfW=UuT}b+ACF~ve!5FkzJ!1Y zYL!sY=Lp_9Mqg?5b3FCgC(4MdJZJ;ax@jw7Vy|l`wpk(#&KBaWDv0;4i_$GB7K&AW z6dw^ye16wN4qgla&rY}g>C>3C3{-Q9o_jbsW>j;yj@|k;^0-+=xW?vmYb3N&+CN=-LrLANQlGY30H&Gw@L!S=Jn!A7kzP7Qd|CRr<KR`tnt|#?(G9C$ zOanzECeHxSzlCywg2MnaBr0_)tlY9&zaX~#?8}>lM}f0*9|c=-ex)*VdGKq`ithR> z1nie5{|K{xt!98>BYwu^FKL$?xIFPbImxPQ8w}39mB)|Ab2Ko{pN`eah%82OLL}Jz zdW@i$L@jkm3o0v`G?f^zs0A|psk#J5iQ~?t%5G0m4UOp53I)EqU}#-RK?T<>O(D$} zzMbf%*F_KfZcf_|522Y^i~T@5yq%ex9fiq@wd;tw3m~p;oMSm=Oz(e}e0#Cy+;ipx z3tI`5h|3X>nt997#)((i$S-M|oE{yZBqgVLlL4{7m5Q1{B?M6{ zm6I~Z$Zz&rGgdQzXk4xSK@o4UQ7^$F7!i1Xfc|#n-aV(d@#9i&rNdmD%+ywwYIZWnML$?`u1b- z0|Q%7dE_{(Gnyu^5>6v#-1>maQd;V)jo@XI%6U8mp+z;|W=9}fS{XMydWsjI`EU<> z`xhCg+__6-EFWl@Iq>r&Vk^I_)u;0L=C_VPzQzhAnlf`(({T>uTAQl$T>kn}zFC97 zwEsZ?6kxfa`+vF@Dws?^)@byVTJ^S}3>P08TdMvh<1#r=#?3Nu`n-O?{Klw~scGk% zxZ{~TB!O`obUuk}dl%1PDWIKt9f3&WFaGZTcB;zD9N$6H^t2Q0Q1mA1va>&yztYjLC!+iXgOcXoF0s;34HootirtUVrru42B)6`)Rmgu=g*C9 zni99w%EoZ&uB&w6jAD*N4GxuUG=41S+)46D6N1=!c9N4Fjr(1MP<|C~gw*#a!8)Dq z3bt{0P5*xA-|yAL5-q=oWt8+RtX}NF0uGvDlR^oUiPK5cwxx8jFl^~`Gw{Y=XbpT$ zk-V*gI13gBsPWRsDAP)ffxxq_K;+!4yBoURM}t|}*WG)GO|*jT^W3K|)C{|i+U0)~ z`F5c~jLM=lAE|N$#CNbR|5hh-LC%f-TFhHRD3?suEnAdv(>9b30y!dn1CCqUzo8g| zurA2kmZy|p{ujK$xqm(go&Pv9+E`99qm?_`m{`Cst%fbF4$yQ>HkAZ#^`1}(y&&UT zH^UvUNqYTKX}^QlJeZsv>nMc=_OkK zz*n{5_h505(q`O_-wq{6xt{yP>q5)PUuBYjnX3`--=#==#+Gn?j6880R1ivaAE_6g z^$cLQyf}6$PIEK!JxOrxg*Q>fkhG%EH!B zQb-`_VG$^PZwT(}AXoG+ z?q@P}Mtqj_cvD)&b3SykHDaaCGrUBFQX@v{-f6Mfh`+P27-4S0xtaSoqAks<;_MYE zzbE^>9x!RKMN&7DaCmppa3%ccjv$JiR@uQ?-o2BWz%DPH@9$z|cs%W@7?v1D*lC(e zL3&LVB1yNI6)&dC+SD*4;a5-#j9{aws6Ql@XGRhSLDAceMNYb7u2)m-n>sTdqxauDoa@Jw~U z)XL;n?#hEEqZ6tw&IgL6Y7H4E6!!qH_ZDyTRp8%5t)Hz;iP^6E?W$2~)_7L)rvf{7 zbMIt_n$2nYv&*rMBO>A%q~`eady~z?j&naQ@FU-5;JnUU(q`&rAts=gUSB9AYO&%7kb|TkMednAs{|rJn*+PvXjCC@3^xFzaHNu;!Bk z)Z**}ABgARHZ+r%pRsJ-H>Fc-s=H!g=# z3g9h}U-K)rDsXpSRbxXb!Gn;7p_TY^uh6t2M=HF>Lk8!zA_l9368h|rT;yQot}9`i zr@tuH{AsWV;>NWmG?F8r6v0As;P*Rv&KS7J^9{csz3tHaoxDZk1?8RM(93 zpQmnnW6~^-DRaVRj)TWQb1o4?5kJ3gmWx_bTDwx#Tx_%oXSQ`Kh5_c__+jFN5g}lH-J@!xQgH zq9Mdr7>U=fI@&3wDk}=(t4CgF%NIKPXK)*>gPIyE`z8nLUT8l{9Wj*Z($?vuu3)+~^b}3x@WNjp0%8k=8S2|(n7-zj~V$sN@OX0GrXj+-z3y9wY3HRe+_lQ)t0o4Hon~&5y@71n9 ze*E~+{YTvj2%fvQKfEKku6dhBK}bPkU|pUsM{$wkq-erVWk(l4lrNcPM|-}?Rj&8n<&Ny^czxu3%dTS*}Fu4MqIavc{RR zf5-&&^tZmrVDHRshc~~XdRGsKuW(Vzq-mo~9ff>S#4M|9$lJMT=F)STu7%e5U^_oX zjNe=E{z52S;N>ls#F1U$8#?Zbyzuz?+SU)@vh8*hX|t<`4@^$evUVcCIRz$cOA%)N z*C}}5Gvt*#BQbP5F3*y{W4A^;g_Iddls1AXEF7hV1y{wQ(dyycwGHfV$(R%y0K;z@ zUc&@8+7*k)QFd7DnSb?x!@ag(4f+9W4iD!ijwI^gyr#a2cm+G& ztYsxl4Kw-qxNzD~akJex?^_kqvdbU?BHa-Qp*|!gy{(~lZt=R^>hfN|$YHAd8eg;U zyQ4^H3Rg(*k+0u^{6Dd_`xi)Oe&zML-_&jH(6oh7CHO$?G&=(`4JA%bQ|zRni?6A< zgx2xK6u!#|Nu~i_`>nlIwM`mwj^2z9Tdqdv2x@(~pZw}R>l&B1#Z{5zE4kWx6j%~& z+xGW3+w*s!iEQ`5=7A>)SC(l@-F>YX#ij$C4k>D%{$`W?q0?w+l&zhnO%Fz`Et5X} z_9*-Zf>?XFud!`+yj3H8gjp~2e75*#9=Y3;_4Vs3Gg(3H)J2X~^9=h5B}jG0rM;%K zQ<>$(&@^qM63d%M>x#{}l@%o>=ZlZs;P>pN7q3K8(k}o*kIp397DuG(t0i@2r@uY7 zA{=w9ag%;@_gM&CUF#o6b5D34i1J#wNO0SZm$Z618Zrp>{Q102BWb5RG{{)nXQxJX ztiawT$GBm|?|4Tg@8y!RWzx%g^^c17?8oj@`9K{Ga!^+D$ro|1^*e9Ieyq5!Qt?Ko zmRxCep!m%3lbkfrJy`-K5FkBHH1tr^mtzrUxvE4;KEDKc=}JQV0(jAVlkqU{bWiog zVl+7yta;<<#(Z!BsYMEcNIud%nj^wx(EMn$Lc_*)qgz0>p=^($i<5Y+TKF~OwSUmk z=-$%ps$QQk23SC;e5ka6Y`IGKg}yt@l_2QX?3EELGzuW5S{{fDYR9(nlw zlK+l`%)ucS!eCWcN7j+y$`n+}{1PgX+WO0We^R`(9o}RQ%L^FoD{B1iv_M|w~JCbsQn?3Ej zI0!c%8I%gVnQ)g#;?Fvkrx8FnEZ>^QH_{;`2bE0evD~xeCWU-!ydY6BYv#86)RS;m zcg}2A{5^lxkNO^uP1zy8-5A|@wp0SK#Nks?lzxy~whlPWLf>oNt@l{0ylnmO$s=#F zqqRxo@xBv@DcJu)`O2RgGq1_Rl_x4`%-`>ef4dKIp4d#|Z85fFzQ0b6WjR79 zNtL<=uUE`nSfpNAxs2{H*Y0SV92NO}FhTiMp1ir+Zv|sFHyjtmriZKg=8DAiHQktx zOLCfD?lX^fJkVo$#0^R-nR7z3Ljoxx{4S4Gw(PX<($-SehDlX zEr}Tr1!1E5n^jdVf$;-Mfu|v$yyh|QrkD9M?_-_8+DMC}ivC2{3j2flQB$khX4uwZ z31=wt+ri9VKf~=LE&e}#uy{#s2YTikUpWY0qz08}9p==S22%B+s$G_JYm8}bE0mqT z<@j?=szY#5>*o+Truq0t==R|mOAIe0duax*@#1IJlpz_S*D9{U*{nKW3d*-c^P|_G zAhVhB(iKz6hDVevZ$l)whfApMWZH6){U9q7%3xX>C@{H}AFS0WegUs{`7Eli&+z?> zzvu2vX8%jz%MsLXbwBpjtD`F`0;@0U#XqW6r;9D? zX60D`M_Z_r;9Bt#Lg%a72fK93gT`W7?&hbAv+ae>$xnM&cb^x(A$d<;dHp?R^OeUV zFxh3SdJlJvYyBtA#YH0MtIk7mop})5K*|Z+ylz?$_VUj&lAG0nFVc6z7u+o5%9c_O zTA~l+qfHF`#a+a$Z#7*yw}}3jS>HWZLe!GjV+1&uvRQypav4kihk;K$)UqcbXX z=aDk7w1fN2m0qg@@XeD}uX|T{c4q6Aq${SpO_!9TcAWwT%j7TdQ7K-Mf$^y0UwzYS z$aYVfm@G7vCS(lU5jgOEW)jt61L?Zl1ETtI$t>vW&NyR3k>1%2QV;Zl)Z-y_2>9b6 z;!pweEut`fubmbi4&r#^F8Q*-{Iq>wavc6#yo+?pV{f^rYk0HPsoX=p)8MeB-CW=f zzvYJKDf1#J#}>)!2b9AECDvWlk_q^c{I`j1KCt`sk_V<$!DhR0wS`Q6@gqfDHyREz zXg)FfQZ^iJB5I?|kjmF3-75ilg+I6;Ia zI9to)hkaF5!|54`zd*oA#gxMAx8I63t=$ug9pg8t%$Gh`YX$aoz zO(bfQlGD1_hTm&EzUHxp{g!k-lJ(5Dbba(L(pS*TUMlcBsC3^@d$LuN!nC#)Vq^GL zDR9=o+6sI2Y&f7RnoS2nJS;2R|4F!vM^m3ffqielhzCYLKhO&gLr`_1oZqa*(g*USET*=pJ-gk-d{ZE>`^(<(?%D3x4b|;q9BGbUv<{+e zg0Rq#(~_HaY;Z@SUOk3lQ?1>Gm_pp8=GZfaKkTn8v=$$@tVbX97~6rw$8v0jY2!J@ zYYgl`M(dCYj2w4x^IawgT=Ahol+7RSePB0_)O);$2!S6O{kC~C8EbZ<+Woi9lZ$wt zU}$@YIY`(wUp!-)6RYa4YqgVRxxv?>Ib@(ZhGrKX)MHxi;P`Ucyvh06wh zzwBK+)JX$O7w&n{0Sng_6_y z8U`r0x6PSElB2YGYppFaKE%C&)gUjuh4xQ?yTo_dsqab5rcJcMen;<4*W2djAC*9e z7e6rs6$IEaEKd`EhV6}NX|K_KL-w=7xbVk8fqHhKQn)7|{Xd+5P9YQx3cixQFY$L- z!3n!4SU=>{%e(zkOZly|H#=@7t_-jRbjZz=nF!1_ZSnn)1upp=^g-FoU&96O5u8MoQ`u^r@Bwh0`N{2jSKVLmb7qUUmN-a@0ft5*6KebkAD>j#20}>VP7Q-}7 z{b`?FGue*1v4N!hk(=Rk{WiY_Zr8fP(Pnit&ib>Gge{r zKC%%J=-^Ih$(zwOe9lo1flA1Pa03xL~3x&ClYev zc`0c~0GL`Ziw=Qne`u^&Rfd2;TO7+EhG`64@%*>${ldZGC01 zfWW;LWHdAtlWoTeQu=q~8_^$HUyyt?lJQCQ;B{bRpn;3(k#I>)-<(|EjL%evB!(Xd zl^$0s>8HW=Pnx2Gz6lhrpLMadeVSf0l`78QPgC^UFZG*+UQ}IWXv0X>viR5`3~$rb~?%u8Bhy6#5HY z@}CTYQ$&cZA!PlJ=S99}qNwLA9vgSth}}omBmQFOxBH<&34f)T65Yu^&if2MGy<ST&k3efq?pr8yz3U?2O4WFAgW2qNd`oBF?X1O`MJMIO< zV38POzeINamE%qfd7hXA>BII%)0h?XmZ~>s?;c}_1+vy(pl&+vUJ_qrzGNDC3H>wL z5ROCfr&IH-A8!~YDMuk**-;+$qV|CllF6-u!F+1+NapOmK zS6>JScVQT9JApftq$5aPx$m|*KKlxHgZ2W0Q!SRA*bIHI_) zZhd-uf4uRHz0tdVlXG$b2+`xXyfla%Xz3|73+2pPkYr?N7-h;5c8QN%8jrUF4;;+3 zi0t66aG;N|NU<3m6pE`NYJoJABIr0!~v zZ+8nONic6@0TJMAN6=<(pmKG2&bdV=rIuC8C9wb>tQ4zre_TIzVdFqP57L1SU=4qq z@1v15Pfho_-My|I;!4kZ6<-qhZ7tTa zK$^&UX4$J!iEr&G^bE=BvpNvd6)r-T4`S|Tt9-W=oNSa|9}Ma(sO?uef`CY%VaX_^df+nIXD^jM-*S~Nn2gKCu{GeLx#}>cNYRU(RuRB8p2YOAQ-485t);%JE zMMf>xy)H(B7ArNk;Ys;ao>;J`aj~OM3P%m(9$HOAE{{jV9Y4Jl^`Q+yefh>9@!HSn zPTT+%@qa&v7&F?}j>9RDg5DkdH#SvmddTM^nxnv+NE@wkW!WNaDGx~E4>FezSMwXy+S6PY*g0(L3l7Dm{H) zh(D;h01@!!6;QEJT1=sa&}go%qd3gYm@d_z1r7<(^gM)5xGSU4*NYp-AkC&)GC3r@ z;ty639>tuYqY^pRp4Od@+*59Qgs+yXDE&liGzI*$Y8eD(CwmZIYjX-xH6MB3*y>v7 z5tk8=E%NPW;DY08JC~e_ugt@m!}V1}l&95H&&2wewI;JA+6Vo< zf9nE7EuO3om;lP+)GT~|8c$n+@YCY@lr9wWX@FKTnqiV zmB7`f@4~=pyoQ3U4xqsy5=hhUj-QrKiXU7Ir}7dPyYiw48@$_$Dl7U7~Tz!S90>qSxA?(t`G@a|$o*JP@D z4N1d_s%iUvTZs&&ymJu$`LcbTaWHR?gmUpiA*XQrI;Z$JfxzU@14GB+7wkm*S{Z5q z5Q2zBC+|A3o&$tOCWb52;>fG80VL*KZYwf?V5=$2B9@@vF_tOE1BcTpr{UN7o8I!7 zpTlZtqtRZ6%#|J@A-Fs+PTxIzgB_^c)tJhdzrh=suP$L|JHS!*wIe!3q)I!iUu@oD z5_^yuJ3@o{uC$uWVr3_?#l9+ZJU=nsArh4I?{gnq9^SDScKovSD^b*+?GbI~6##(| zN;v{)m-`bXp>;=`?GF^EE6p1=1q6w#r1dTG&4-ydnJ?_unxZtTzAD(xR~4w0D2gaN zG<9Z(2a}5JT>uFy6!P{f?FU5*#H`QSJuY?Yc6@5Z@~{yOq8D8y?&nVp@$USjPRNk1 zkCR(T3q>oMO*?2K`mJtFhlLlb&YaUzn?}~EJWq6nJ)mljiya-|GMBC39KELo&KDmI zk2Tp3?f3JKK9^`2oPPAaK1sqi*cB05&$moV8)7C+t$bl8^+Yf1KXEi?TV`3^q4`44 zU#WH9knTj+vCpi_Y;()J3j}%Cp9VqNU_0mle4D?b=Qxw*yr1}C=55r=4e}Oj@P&jf z&CA>@fh)@4II)a5pPf6LquE{d2!1rl)v(d+;vfPJ!wz}&YdN{?|-0 zVF-OCFz=sOsD+bL$Y4{N1X%ScVjyO#Gyo^i38#KJm5>b|yZ%#a(edM%2)1sOVu-~?vEs5#@ao0jK3OJY|`7pH<{6Tk9LG4Fit9*j+- z5VYGA@{Tzn_Qy+KYjG(iQ4&-W%OC9j1@6rFlt$<7D8;z9ei&8da@nvCVI}01@x2}z zOw8s)4fFrvc+_yN4pTvf5J3BjJUbtU_f5jgth~}DJ_I(xGCSJWi_me7bRIXJ-vxCE zF!Puk;8O<84CX*S)mu!&IaFi{-?9!Dar03NL4K^C%m>lYaf0|)OqD&sGi#@I3e{ezpTpW{+YX&aR&DX>@`?m!$(KP|< z13nMTj{=reN7ZVrBsgY9sT|IG<0VcH_ei9NP~8LQcWK6gu`@R92J#40gf zG1tk|?D^`A&%jdcx)Ub@iHmwA1aj5>Z4X*+@mNk{m;F2Nb2z#GN2ss;lf13<9eW1< zqdN+uW`<(X8@h7wH`^Y9^t}`LiFki4oK{4zvT3dKCFoB&8<&E(#2?7)utZn&e^vw@bgtaD!KYi8A2(W88}k$G*KXcMq|_9aO|WHod^%W^YaE>D?Ji>m}e4*^6eQRkW=@ zS>7?@jXT*=Eq44pLI4toIagf?Ck^^wHTQ!VTk-OjrOIYJ?u1G)9h%0oFFMZYl;j6l z@{!O*WXQC|=z9j%1=S1-hp*yF+>8Adn8IC_JLgzrY~DfTd>-iw8htz7*WN_7cxOu` zBk@_+4mvWHN+G4j(`J9=i^^v$p!4jy%`R1FzDYQ5IWNV$R(D9t2JHNeFh$&t-toHI zE8kReyA84MGfT5f=w>wHg5nVQsFI~tf69s6F4*k#2^&eiGjoW-115B4KA6&$arjuLNNxVy{ z*GVL5lbQ_jl{D{@f4pfM`EkfKfSLTJ=+szZ!YwBzv zKl5_oY<%N6DFNcA5Z9Du#}b-KT@_yg2s(N;u*Ym_Uay&%fm8e6xnB5);a;x|41@Ou z$DC`(2MD61Hr}65K`S=3-}sfbJoEtKWT6step|$%L-%P1gL^Wc@EkXr!QClaVH6FE zNw4`DA|%p22;oZhz1`I+S+==3ok>U+^c%K0PKtZ8@rDgL!_WlEiSY=%FV|o_&ii%O zdVZZZXFIQJUk16j^vZo7>*aQU~bW~jKx?RPc2D{n|)n06pS zl_}($oXn=PH==Q<*X%VwyjgEGWkSK@QmC|X01`i5aLjG?hS%LnEHn`(v1*M^pDs5h zyj60-kT4&LPqP?%2s2#u7+K!^;LH9XI#Z8NC^lE2QN(TfWGT2!;#TC?<4?ICC_;99 z7_|@~;yuaPIhudGQ0?7MC{1qQ@wLrE#rjjygF(4LJqM>-2X&G2EC4xfE|j~9_>PN3 zB7GanV8m;`wP4gsd}^EI6BX?#=EVU3n*fXveCb07* z$4?dw^Ix-zp&xH>vCj?4?odKT$1P7dGb;KU1O!czL?5vIDS+F+Xl_!5G1=|b$MdJ* zXl7e&8+MUw!rD^Xv%d_oLU74x6*P`OV6N`jUxzwBV#fc#NGC(VK6dpO_`54Z8_LOS zX>2|d>ps>n5=VS?Y-A+FY=vIv-OW`dE0smfP(`)3fBQtUy+U=zvQ!ibzDqOB`SjVE zxB7jQB6V3KdL1z>p0HjcBt*D#3+dN0943GF5b=fO#sk*{Ncd!`+=JQaABn4Epu^8i z%eV|unniPAGB2TD{(^#oVSZ}+8$3Yvz2U1p&V5c0Z{LFC=)0H&DL$Z~f#lPAPJYt; zez8z~3Uhf1%sT8Fazo{E+po%Aa|94QF20U&$+B;x!&lgcGv2k~!;7jR+%pCK5vw5a z^Qb3(5_TPyy>cqi8t~z$B8-$RpBo&l;nN$6yXXA=gls3SpnK56SKn^m{GH4ZwJ*Wn*$>S&#EDw7-({4Chtq#a{Z28I#Nw$lp+1LMtqcQ#*H`Y*il z0EughKKvZmzTYwm{^JaLg#=;Y3R240v$+%w!V^fb^50?#$7s*TW%K3V zkbon0%AwJE&s~!i3b(MjeP&6t@RXw7I7-(ZCfAlo^783|(-+=5gfFdGp%S?~t?5uWR-sR%_oxaxUO4x$U4uBr66$*WTjEKb}< z!?5hdhB&aF^;zm7p)-}$7x&Ecg3J9%T@?25Km9f^Z*K-6M=AR0z$jcXOU+)Sd2#$} z>B}5BUPAJa9Gf8J0o)f6hFiP4nbk4XxD|2nx}|bfMR;&}Kf6il#eLnMf>5WHR6Wp&nQE0tvC?vQ4jVoURIb zUG?>yk~?`OZ`m_Qcfu%#+j&npK$duk1(#vF-wFq|U&12feEFK7^5x4s=}^2WdxLi` z{U@Jrj!O+AEK8Bki=U2aj1yyZY*dTo&W&%4pWh$OsKjBDTMM4c`a!qR8gp@!c)MgU z)q8gK6|%yGHA~5C{U@NtL1lof!NzwyRH}{4xfWbAoRKA>0t5qOI+Q<>pN~G;|Km6@ z!Pf&`nio{s(G=0r_d&=5`c1dNBdkjGifXBTrtk|Pll?NEfzK0>_TudznAN&xpYRY> zV!|Q*tpbH^!(@kCEAFKe?B&O1uPb4T_`{tUK4E`6?S!WD#lsni*y!rcyTEV~_HFaK z`*YS(!)K}Fr_(ci{Q%?6r#s4aiM=-?iq()V|6ChvY_G-X(hD`BVR@AQus)XSZD=-5 z&76h>|IsaYxR7&!z|Vj9LE!U;cSzz!xz=zq=Lj7cQLhe|0KfIgk{D{sA@yH81mrJm zxxpHY8fTzIOSr?h-*rzP194#bG@1*YKs+3V={8zTc6B5_kNwP;g$`L{J8Q`um(iPs z(7xg#T-!!N!~*473R1&I%y#f+@`nKGFKJ3a`(iQdnx!F7qA6tkOzuBDqg*8`1iLAy ztt0EHUF+{xq3_FG1|T_!F?j`i#;*O)9E-`mFDmly3E1R{<>9?I8?rN&LeBG!d`~kI z8l99~B?>E~YyxaAr=z>KtK09w`Q|(?Ctnq)uM8>kd0wigAAOI!J4TH*e(;vlc4N`_ zC3zl2;m|LGW>mW7eLX24UX8YCy+6K2Vj43RONoaL^^9-noa@JYxvA3JywSKE({f2m z8;uy<)(t*vaLT)?`2>E-1?99!%c@j81gB{X;zE&j6a_5S0g)<4F?uMyLUtg_oTuuX zV5QO9?2)|kv*XvV41cgqkSf%U;7fke)8f?1r7vj*L7?}T@Lh-RvE96uPr??*1pYA! zW&CH*{gHAsUj8U|4UPun-zbyuiYXlP#5RJ3|Cnc>xE5Ot_NV7AV)4UNq(WGUOeL47 zD_0|Xs)#GwZIXgZDFaGwioawT0B!f*9@ON3XRa=cmrNVie%1(bQb);t-s1^w*kC(D;kQ+AO6ZTbSoN)wOtnrGM|RLo75Vp2{2M`H4z(dSP6>xh z4{U6kfg1$jg>aDwc8iddG1VJD;=n18=aN>hIuy?D+55oS;Isr;$=n{4lblQEGF4vn zXmFcyth#APDE>TjbD2@F$2-BGJ$<1J9o!%wPFT zwb+ere-WIu_!8yh3|tAtmpy3U?TcC6Lw#(p(b z;B-x{lS*Q|wWXf3;0KG@m@GSaTfs2qkQt1<_RUMYT*ZjFBr89r(^ zf-{-pgEWst!`EisiqV^siqs$k)=V$k$3#w7iX(0AYf#S3lVG6DLX~w?f!5tM<=qwa*-ZO z?f&p2b4<#5c)Ythmq-ONX3lp5f7kon_sik+2Z4O%D_11N)@ym82SErF#6y2;mc+_% z#|!NnoCe&19EY`h65((#iHX2Ar?XJUd1pp>Dt@8iFo%B2OtQpU8rp#0<*Ou4Lq&P8 z?o#0w=N6BlAToEXBfL!*`gvfd{XMRrU;*!cYHQ#B)Yg{(*aXzpfVYG1qi5u(4PZPc zh-Fsz*9^^M1CThoo~VL8Ur5vDrYZcgqFT?*%bcnnBbh~GS`{f3$zKsbYYww$9Cf_7 zl3k#$cKqIisO%0Cv+GfB@}^9@Q7!yze1)c)c6rK|&NG)4Ht{llQb(2kDFU0!>(+eY z&&sT0$;`j98TEx97dxe&<9f<*W97~}RJs!T!U(4F(NwxDsDU6-)0Zy}gYX8Y+R(5L zmn?NBGqMUUy$&Xgy((uic!K?hWpJQK-pbD%?e_BW<6*&EdgGV7oip<2oQ9oFz4O#B zy7tpbGSn70R3w@8KoU6qdPjU#g=9gQpq#v3nQ1Vqrl+SRAUW&E5bu{eSAP(&<^$GETA<3`Up|a?<1Db*sX@|jW_)@@uSL^Bw#s&pz>OX0uiB- zNwGKh`64tiM^G5bAn56y?|Qtz>ZZK!xzdY@II$3@sakuc2Ib@iN;4~M5!f(hxkiYc zi2cn$MsOwInDu`pMbF6}-6SND%^;86c`H4vSv)EfnA-D1bh=ujnzm_TKNm8_WSmcr zz5TLaW-vy#>NdjL*OGdNIy(9c);nMTV%$pI>m00yWD2-(h!J#ucl|Rnwl{m ze(y&u)W!Dhtdq4*lashBlsq!<=6pLMcOTB7p=BqMN7@e02bp^%c_|Qs4pDibRI9fo zE=$AznAIw>vK+p4mM;dv75hp@u_Zygr)w<%<5YO_tteHL{z_eCJRxsU{@WA7h(gj8 z8oG1$=9PhRBtMEf;_1=Hpx{I%eW58{X2x?+Z3 zs`Zs6TWX3;+f%%aAvSKF#DJf)Cre5R&xCl9OE=|Hp@ii_@zL++6$o5X0}sBHLc?8u zL%dL*9Zn8GWM4=B^VxB2fyBTV((jBnv6az6BiccL9ca=C{bud<< zKx_ykg^+)%fO6`vp-b&q(cowk0oim>24Z%tU{z?k<0~$KEL@>aGB*w-KqwcB>)q&5 zDQZv%{QlY`h9D#0tz!Bph0^&4F~6|7#2}p?(bWI$5#Bxsyzo*Am1LydT z&H^|RbZUdPR4zlSaPi1$1YGP#iWi3rhD#L^Wu2i=ufy{b2z>D`oR&Sj3QQs@54JGk z@Q8eH39yPH@$_n?%I<|$YLduGBM#iWzQQBgBlC_6m9{@0%5grH|4_-@X3f>ZmRI*@ zYss1Im%-JQ9Yymo*^dnJ{Rx+&veW|x>+0V1!#A~Dj==wH8UN9v5A0PY$1Gf%;xQ@5 zws_=vm_RmNaxBd#@bV7~+`Y+bJVqhxc3O_SUdm}a8r#X2!HcCd*LE#!S%F8L|0gtt zYh~O=cEqq88G3tL9s9T0iOMUBG-PiF&Ao-{oojdpvNA^AZLNZ`GJTh&cD+G zO8K0EpXgEpg2ZySF`VRb`&PV9j7{950-am7$+^*{)&ff2jV*o!;X+_jz59{Orq7`U zWdV~0O>kL2tv3_8Ey;KhY**WZ?2lg#Gq`0sPQ$IW-lFy)ev-;*m8pK|5o@>%6UI3VG2N=9Sp|2M9ICM&JltZn z{3-j-)FE1oP39l-{E^Z>#@!dVY8!4+0Mgf{${Ys&1nDm9=|8sa*2}{xy`jq;^}d-G zSU%hrayB#N46a^cnCkz~^W!8@?ymA$Ty5mkkbeB=Hopk`lgJdmyvXw+m(GYma7GfS z(&>T)4*DXj?pb3+j_294w3m>{mzgYT#Y8@Q77hG`xKMHd58Am>6@{zzrBnOmdP`0r z*a@eMrn1bg3JQelYkP}pDPbqg^hGeI-**5LK3Zx8>vw$b=fOhVM2RIgh^UQg!4cgg zW$dz?+%#^m8Plzf#Y5Q)f*I7P2=#-z25*JWmRdRO*SB&0{>|Y8`v_g|>K%k&Q^ouy z&vRiWqo3_`*8ZjD|3JGeSU|rV|<r+U&AOvuPHyhaEAbt%Ed8wB#GJ-$-Fl@fP zw^`gzOd8`VdE{PBoY6YLn3F+<80@|CzC9OsewmB@JM!RZu@Cv-XHHd+1RS3^FX*$~ zLG9&N&MV(C5jnBw_0X2S_!hV+)deB-a()Vd5B}PGL73O+; z2ri?=;w>tP?CQ20)+tV|^l>AG-~+@bD#o`q$*Ls=@g=9eaz&P!;fX%4Wqr(0l7D)? zA;ov<*#6)nr)y$OH-cuFJSJ);rZp)`t-6`8MnS~_ng+RE^;~>r|L(G3kzVIUO&#`8 zYJ2iqtjCG+Z!Y4Om~~^e`%?w*(M?dXzGYjl5>|#dTufOil(vi z6kve_4#npZg|k&ahVs1wV-sa(^-IEZ2EXm{!z5X&30fBRepd8c{doNj5BS_`t>Zg` z!7q*O5pjI!33qShkz}RT^k|w#q(@=fCR=b~yLYD?d$z;gvV_g-Jzs|VOJEiRzW5OJ zN?jd1^SKS*R>t##_HLW|3bV2F;Bu{s;nqW~{5o@47{_c^@@-0yT=JB^)Cc=dFA;Lz z0W`J>3!l@l<2_b`bg00f6@|Ckc~Q{_1f`q?qYFbVlg|k`iAiPDw#jtR_r1gg@_q=; z(M;@Xl(xGIT~8nx2A7mc5CFre!blVL?Mx<*LkNo9)8tgU}q` z;^EN)L}#4JKH8HB08^^5DARTlf3Sq6UG%yqa+`WpIC2Lixt}fDHx>~{_(IT;8BCV- zC-BbnTW=;WI-lYl^vHq9EKHZ*da}!R*zt7vYSwQOU&FnQ@(SF=7819w1?;q_bt*ug z*Y0^hQ66em>$DiapHK>TtDwgmiqYeDXXxv^*G| zvn@Xd3LoQ_>3`~J?*Cq@1KReFfbu>X6_IGtHNl{T4nEOUuPWYe_x-j{g8UaFzEhig zIIcRj{Mpr`lVula6O51o-q1>6kksS@ z?rG5*@1_+I6gzT%CI2uUi~n}6dy5jojdJ1H&U{9`eXjCC+q))gr(MJyEYgKBsFttu zfknB#T$s<_Eu6nf&S__`;5aYEdh3M&>9E;Lx+FuJ4}hvqV@zSjFKbc5|^g z>2>TGaFEj0G%>SWRhtd(Xk|sR>bq)7PqJ+!glI3exTV#~@`lFeKQe7@Q*1PxnWEU@ zNon1d8U34tf)1jM9eW%S%{Qs9W#~=kGa*Xt6l)#CQvZRCXTv;kJ}04%Y52^50TszE z7k3HZ*D8Hc50Wwytw>&Z_dKq8~6Os#ds&Q_D@KBr!;S2rO(ODxk7 zVA;bzDi`zm za@MPFoKgsCKYX}TNpU2e3e%^xFRAQ{S3P&H7(q;zG(W$>7Ps}wkvWb=n-P#=TOU-{ zNzG#vLy5WTfXCYm_d*>z@@huY{tRJ@KlIOa4kci2!UzYImGJL@-0{y~7f4q8+b{X6 zRiU9XB7}^pb;xM5?$n<=I2>uvpyb?+9Ki!yE_FQczLykJ57xu!+y&S&GM?P~rA2Z~ z{BH!(esZb;3vC&{d`j}}GCOY-I=+#Ob-sG?exE-f9(vSkk*KzV}ySHHVP^ETl_#K>D5(NXE z2Vj=oS3t03R@1|uIXTX7T+YUl=xP~m#-B91xl+BU>^5mtURJJv_SdS6FF+oh#s(d` zYtT=47lZki8?csaU-3_n@PmveygkPG)g>@g45x6)nXXfs%gG)$O(YN+Wk*`u?L%)M zq8*=K^L(GR(rtNgA5MLZGKO$!Db-kd+Fdw6TYNM?8Ru)e|U_ItT%8Qtzkiq;jOxZn4}3L_zWZKPVfpyK^bT zm1@{@4*d%Kk7o{syJ+xnH8rya@icf|ywt_$00M`-HkY*+u+#1oZ?w5$D^kkQoOSu3 zBVy>e)(b%`BHZK+$N|jo`x9vxnQG!oC*-Uav`Lak;sJf%mqoGtV_>dr-?j)S9+3=Z zonNHJFLMPY{~aPMDP4=;l$&W(?~2Wrez{qn&My|pXY$Ty6CbPeA1dMp?2m`3g%$Qk zX!hZgCh3UF&Dq*)<9(~doPy9CH=Z_-u)wuwZvUG=H-*?^k$_ip?`TyW-`aj)I_%Lih zAh5Lq6PTu4s<@M4S#}DMsL5CAParnW@Wk9)%K~K5 zW!~3XA2_Fz=j7NyTGy+$Ws*aekQm|2dA3Y*g$mu?y+kf2RX}5pdb(B@4cKpbZDR@4 zhFBVzJXt2ZNC5TEtu79;^ic!ST6MIq;w#aTP*|G|21!IXR+mf{ul8q7KL_E%1cHLz z@g)*K1Fduf-Aa1Y%&BL0Yl-TMClEMD@qCXLK(oyzwp_}+g*7!8-;~&b0^@y5tqcszyF$LKP9st>Wg>}@{eOA1Z2x(s`+@^C!|?=hs8mieSK6l zJSx#2;3jX1c%#)g?Jb#o6~&@;J`RMAkKqb)A&72U$suo*9#XeUzDQ$vTqHd4f#jVp zpep5wuf-beCjF-pZVprWBdiJQqY5Xe`WS_!#du-pr`|G;woLXDG=R#5n!Mx!j*{O7i z=fcAX5|!ca=H!lj%%+oZpLZg44z7#1jwZ`mOHI@@nGB-`V%#?rAUgwNv!|6bRTnj> zwp)QhiEkBbs-NyNW6-10FBSh?a}F$mAn`mIQ*{hjb`f^wT>wa-a>_^n-L4nO57$`A zmv&x>ej2B}Iu^_u(W+XUeG`J0=XG_o=rZk5;4HY@;+nw+);+}AtT*m`d-QbOs}q|V zV0i58n{n6}^hms}(_y?*Vl_XS!=$z+-?W3-P9&?4E`Cb7sGj%U^X{MNxpdBphM(@U zU_dv(4yYag|6lKLVVEfo^c$}cNc;)LEb-ac93-CoRg4K3hqmeAE7iPqxs(vY&Xrb9 zKR@X#Jsk3P{x);v4q{U8s;!sqgj)W}^TqzD_pRlQ09ic@WH?TZeJ1()8zO$weW0Qq zvV`n9g(OaG;2XCr@tis5b3H0_w0gyEi+$+P*ejP9BPA5O0(p(`%T+NqauFRF+I_n+ zO1`1C+>i~vFG%xr+}dVf`M57AtXh$L21*3N$W_CMn9Z2T}n5>rs>*%W3!@iL!`J z6XZSeueq(h{E+fi?5WynjN*$7I5u>5|5UMv9*>3-R7 zL&~tw&U`rYO*1L4^4a_Tm%ts?PcfKE)AbRlI!&b6@sNeUf8uaQ#*;(D-e>yvAStIK z%u!0;WMmWNn_AMH0x=VY5z|TjKPAjWHkl=7Qsu~xq3(_)&WtgvlFD=)zjYJcWo5_I zkANueqB%$&Y}_92^RS_4vp5RWX(W6q?Z2Rb9<+Es^DkD_x{GZWI6|K)@QyoO*rvo@ z4XGAxdxw8HyzGYo%_^vJA=2TOpN&MS_jZ4bk`rN{AH7=Jpix$98;NFR=88^62{HeOdkDLI?+qSawymm?h;K@@mSeD@_^M`04s&RN9;w z@0*z`th~gxmYTx`b*bi^mRmf_%`QcA(O(#Bt00N>lCMV?02zYj-Vv?H;ts zK9R#&bA7cgxvu+DqCAtTM{N=v}En6LC|O_}Nq5Mqac-K(kQSttJ`3{Z{7#Wrkt-NOJ|{JS6cVu3Sj zhm=0VNz}Q#Iu%0a!8>Q0!YMt@%s#daMn@ z`ByL)-_l2*mpILMAq@bEp{jdD$E$XE5xsuXjMolchaV1!*1$gFZZ6l;oX%5&q*;kI z($oZN?}k4|YP=!A+dj`sq>;V*$S7`A5beA6$%W}kSg;-SkUHE z;qglNq+doB9`RXUwpQw8mY$x=&)2>ttiA^y)^0=R{DR3hdHaExj*2G5<#0B@08&fs z^V^(|F)L3Hxp2!8H0wU-W>-=lid%MQ#-SYhJ(2CpMb~e_8*y{9l@2BGFDo7;Fh{&g zj*j64UYJN5^gzDQki_CFER@sz>K7f(&Ef9*;4)NB2ujcd+Vu{EnFoyuCgA-^>D?VZ_lFGYW9!UMAn^$(?j;aa;L@U;Fo2V`R@9k7gUL3G zmO7B4UZET89`u~xu-<3c;@I8OJ;$1|LPB#ik3%W8n-m1#1yhrGK`y)%9ZoxM(Lc4D zHa==>bEn^P_#L9t#b9j){gHn#5l#BH@LTN;k4*lJ47O{z_581;AJRQfs8~Lvqd5vg z3Em`lM@=4;jrI%cSNypvc{B-`-A|8G&jl3x<@rYp3Z9`iu>I3WWP?wijDhJ0`kCiH zwSUG2@D$v7D*NNn;T~>~4Y$$}Sa!HSe)A|3xY+TpXl63+o z1Z|99hjS&J!><#8M-q0s>bljoBtU!FACW><$g3YP65;%$$LBa8viDbsV1f%7%B){b zAN2_JSy|lRKGxyQ*jbpW_5`@@!v5)xCZpV%onWZv|G+>E6zFnz^CYO- zj`yv-&N^XWwo=Y=g$(q{-kg@`qvad{Xlbig#%e2{!G(?fV?fl$YO03N=W4*ofM%cp z`U;G#gPne_jT(_!6#xqU2st+eg%y5Y;VNfQ5fR6X*fzUej#?eH7xwqo9DD9BCImSC zL#wYitsgVA*y^lp`R)79?-32QJLUeVfqgoA>~I#1tCzCz zY@TL6?;)dtvt!r~Reg;?`lD^3SbuAYQJ`V=dyzT+g<`j>^EJxLR5S+f_4h72N5sP3 zJoNKw1KV(yw7Sy%!;%lt${!Ip3)+kHoSwscHe13ZvnYj5DS|c;zdeJhLW5O5e*9fw zNIQ($miG0!4GoOY&Zoq>$*b8~6+@q24PS-u3Fm~a<-C@|ZS>qM+x*Z*!@F%98Y4jS zoto1Zxut(%K@8pD9mC{8&^2bEGZ|*TzM`w@8qs%Q2_b1x*n67eoKpcZqy5 z2s#{U`f85YX_sY;@Wc;~okt_19(B zXkt^Z7-3DMbuv+~tiPKuG<^^5In4Y zY3ut)5tN-g2D9C%P!m{db2%fjH*9{NmQ<>pFl{;X$<~wbbDJQKC0;&Vo6x^JeZ9l# zH}{pw*3*{xzy4gRrbnhBU`%1tJK48RO+rl@^&vexdzb>ts6g}`pY_}^%85ki%}MSy zaRsv<ckvoLeRZ_P>X}aJrdqM{|k~@mz@5@?7D_gKfls~ zb5~fo;Ob3|@tB{|Qtz^yZ}<_Sa)}WU9xQ(0H1p@`_-Xr15xg63d!8h#e)e>Vlu%`7 zXG`iME?u$H>O+3S>&JN1QN8U&t$a`T_pjTG*Q#{Uh_EOFS^e!UO~7dRG#O@a z99yvA$U%;(yffGxX3fz2k@F^dbET%v2^UD*Yjsg}5`1CKM0N%9I&&@kyf!AQ<@rh% zzC=<~-Rj79K(r7+ib|()xb84tWDnJ9;mf&Q{q&m?QzI2N^S_%&vwv&%F{Msq>{vaCg3Hh%m!zun7wg7qrJQEUjMTOD_oWb z;R4|_9j6H6*ig{sU<9?A_qb zbGXNdt?ppp2PP(W4o;sGjy3C%9KCk9Vt?y-n*zI@mm)!yPq$3Wl*svYv090eNUJ)f zoytU`{f9=6ty&XIBNtCv6Oed-+0Y`upgsK$gO+)WRgCi=OC!KMCA{|WN`JWeh@LUr zWA{9P;!j!a>ZKMy+(+Oa_{9(+Tc%b*q9Iv?3k~=Ha9c#NeWwq-?3?inBi6H4B3#nV zSb!cUl~Y^MSozc5Uuv!S%8k!JD&(Fsb*3=^!;bUvck>YfvPZY`B{>W{YIPr{+d=`q zjtBK(moNR}C`JPQEU!37&+5#EKN|Y+t7P#WIm0zDN()Z0PAi1~%?9m&AeD&H8Lc`B z2@;~q_3+<+N?Mh8|;lqnaVJmo!qA}H(`yU$%936%QqUmzbSImAVeJavslV!ToycGDS zp6Lt0L_g=^k$<*@Qgb1zR`ucQUw3}5HVJbaLuRcm+3F-&_W(ACUKs-;i`US2SnF4V z>qDv04P(va=K1J_5oY_h`FX=C3l!P3w^=O*KO(@zTHJH=q}QR>({W-no2i`MQ;bHr#&JAJ%nBj$MBLcsa! zw@O(d=eC#5W7rII0Ub1bPf{cA+LlU@Z=vmWHJPX_d%gR=+tg9yd5tW(Hy&Gsi@VlX zt;-W`>4uNoK+b{v~)EiroXejVjX=s(AG&Pl;O-%w|+R8v&rkwpN92C5r@ z5+pZNQIgLAAoN@$4kqVa9bDHwf#m>6m=9WFK@97)38TFakP#0rAZiy+J`0`G@%mb; z)OFXH)s68*`(_Yw2Lqht8jI4t17|^*GTgf!xIbTuVCDufCdB=I_-QfteYe!A$?jXT z8P&NWZm!~N_ho3sWtbP~u0l$7i$-I8IFLTnY4L4RO#BbF*@KPsv|1WqCqE)o(ls3{ zj^}hVNEbMzY;HQfj-(GBDYZxu385 zpc;)X@mewib<*pwpOgvf{NePi;2Vc&wNVZtx7#``_aa&1!vef@HJ6{$o(~Aa2A8Gp zJ-8>9@1E?%twBbG@`tLkO$w|lWp1YHIHi?#QTYBFov#X%f!hN>tXq9US06Oc{< z${;F2RFonm2vVd)nv^sg6hxXzlNtp9si7kX1f)v|E%Xl3dr3kHIgjtmob@~B%=>=d zne$tVKUmMo%F46%z3=+Y2a?~ z+iyKzUxX8R4u>Okjx%3>d!x(|w@9`q&y9QM@Uu?-OH-VUL2V#;zec*8a@Tz@|DpoD zt00M(d;f#mNXgBFf)r(^wDt1pP(dXHi|S5CdyyZfH~Rd)W{=^3xnrr=P}Z$01HjO; z-kxV{7xd2=6_Kw?7#+oSLRLs+_vx-t4Iyp7q4Gbs6>q({blP4%lvePVn%`aOP#kCCeH&}R{Vo*N;ztX z4B!={jN%92v3wAN)hP^Ls`{z&(-6%dXqtA_WBM@f#Y9e-)9haw7Xz{hX_;ck$zRji zkgo(~vKHdc*at2@mD}8YQJT}A)nB$*S6Odx=~m)d4YuaGkHCrs9stnVC(AhQRSQOG zP*qSt+SIn2ErctBTU7PI1d~08SH6zC+TY);>LC8Cw&X>k3J^)I3ZqBRrr-9bE;78#1 zIlyS9_qb3Fu}LqEClPl}(nTH#fY96lqo#hHztX)LljdpUjX>Q?pIWz6gi2XKslHcj z7L(4oyHq1qRVNlySk-U_1)Tmq8HZ|;Y|qVW+m&51ZWe8e>6Afh<=>t+G(LEhaG#~s zaM4&fxCdlYX0BpyZgiveJwh{I`H2~`tF(TkVZ zf!_Fcw>~(8EoBl$LOw|JKX&?Q_7&xoG5up?-(yKs(RW@6DWz+V`jaZlG6&YD^C}g4l)&Pjt~Up~R}$qaBcQ zW&1>uAYNI>Xe3J{A}Y(_VN*TXFrRXzqPj_XZ48>1)1T$`Bher_g8g`mAz|bqjjiI z*H09nM(T~Owo0Wj$i!eBiQ)*zW(H$vJy0k!ylesAFh%)ZK)50G!geEkpfANQHTPGePpC|Q`r{Sfi|U#c?S8)Tw&}(NZT7u+mJoc;hDLK8$NLg_7HRlc zT`DAb>jhAYDk?40`8irA6PS5HoH*sb5*dY4%DWAz`*gf{=ZAvPg3?YCQE}Gg79A`_ zhH!)Q@i_Cxs;FQ5XoZZERKoHf1nE*Mc=l-5Vrje;XiTa-S^$}&p6 z9USO;(S5YcXYSf(J6Wn{ivkjTn5n|^t1artlUn2T2e*>b+6F_1L>E*XRxWFzTF`GC zntILvMJNs(b<)9K)!=~oqI3PH)0r0d&LS^CK-uWRZXe18Y4D2m42ifjeAVAOO8(X_sHGd5PubDrkI(qg5F z8RZmWyKM+GYz3fflwP%xNgmsFhoWkQz26N5wZlcrgN>TV?@Y387~F`-zQ<`VslGt$ z36Iqs&=#JPBC*O=XL=SJEq z3+tt13wB0G%-{K6?TCx>07byJf0~AGg+s-qo18JKZ!l-`v5Yi>~k<1 z;0pQlae5e#jUTn2EdAE?QuNij!LTCWhuaLRZ;dP|!Ih%zPc`^kcz@4)`Gh4ZU9~;} z7+8_n6`P0+esnTn6E#&A5L0NwlPUA24q)E1_P30-H8yPntJqkY3yyVL4+MtjdL>+X zc=p>nIYH|=T7sp%+HX;QY}=clo0}Y^!qF?P6U1rZwQwg$WS%d1<6&txkO0jsW(xpQ zG_%ZC4{XYsXB(?d_CO{Mc z+xVJKs?Fl5-)?Sw{17$&e#)o`x;eDEb!9BU_yjIml0^NiBpnud;zTsF$(a5gkQD}K zd++Xsf>$maH(R+|^6gcmW=m+BI#VbJnlzB}xT9KXk8Lxh7A$+Oi_Z8Hm&ix9T8%w^D$C^-io1(6uLMa^2 zFqZ4vTX}hpa+LCEoU*es2m+tDrGVcNDV-hPTlrW0{>{(?ZJa!A^4-Nc%B*3M_IFFX zv2FE%-BU6#6y2L5b@hsHs?z+HuFBa+oQCVw*ZjPibNpywxUv@F2X ztobuK7$bJsl_YCj`?RZL2$Q_oYC*Q|hv^4(pL0wYd z?d<$-NLCpjOBnmB1JH>3xj|5(VNb9@aPLT58S?O53S(~P=h>0c zMZ2Rxy{&EaizkKOE%Qu2M@;1hK7P3L^fIgWw^D+(kwQ79A>3kfzP;b)kgief zbMaP}6j+%!|1B{_L8v7=tIKkwpXXDW`WtCNyYM~l1cmWb?SQ_0n$~+;9!c%cs&_lW zf~OnK1ss0;$@h5Y!-dMk6oudCzr}@Ld<6%Bah}h@c$HA|_4)u-ymS+H(Ai-7!o@-`p61-ofSYhO;`bDCU#!r5EhZeIOPuiEw5s9~J_jGt@ReJ5oo&}{cJ zb2_8dZV%n`qW?Map(uW6%WB*{X$6x@AJfrc<^(VlIy-7q4><|x8tng#VRL^Bqj^RFCGY;2GC!f8BH_Alf% z`mMQt;xry`e9Q8&UVxnC2@><|kp zOwKx9Zy5GBuJ7}liI5(8wjl30`!V)~H`i;vohQ-W5&O7o%0V+@b?G-2$UC;91aKPE zW+GSj22f&GGJAUJ^Wuy0l1dFf7PlGRy6kB2;xxQ&6sR>pQ51f%-Bxj)sft^yUzLpY z=5Ns8oZsi0C~nTh!cy9#4vjzlH48ve*W#U-Sly5~e*=w$pjHp{H&(xY?H0S6@bzTH za4Of4HeTJTV?Vv+bhw7C^$Bix%Y>afF}-^Nq#%S0I(O8VZBqz?884vvS}uKD&zBUS zp5F2B36I7}O>{rbJMy`yXWtmq^!&8^%2LAJN{8}H18eGS!Q-%6IbU$rKyRq#Z!P4q zwP>aI4X4Vj{b>RdkGw!3L|L=V%?VXj8beYD`Q!;B&^LRqz_N!q zn4dLWAy;0%Kg{fbB zydAzAUv%jl-{~HM-x+kX&_9)-bXNQ7IvuiFS^v)aZnm+$UMN>OFc7TCSxiXM58s)R z8Fc6P@yYNo)-8*&o>F_%Y3V-dQHj_FX`tctGNxPhuvijq39inT5D>W*iFNCip7J+q zx;0wySRY=ut;xL9XrS9UUw_DU8L0Ep^uMse@lm3I1-a+;uDZQmN12WJGzeM}oAYUw z-{_tfZZ}G?m1nI&{+@24l6By>#LA)-9rPoRbyb@d@#uxmTc_?72}v0yJ_vB5qafD! zooU-imeA-oi5AbrGJF`4k;=OotCkbhw}Garj8xFmqmO&$bDY;Bo&o6%-96z;SZwd& z5;N~bfIA(7TIllp?{_)U!NPn&(4)aNEZPksg%f z-fwQ{z5F?duU_rQ(N_clN06?6lrcyr*P*_Y)%|o;DGQ_~X`i0MU&ABSDIi@P0!%o*LTM10 zKktF#Q2P>^Y0?RZmAiTha4`317CG;P=yU zsZADnx2%ls{2X`kl-Q;4^;gzm9mY32XZ*u{{#j8min~GR*gGj!b~)wFOQQ&3ce$L* z$;$zUn`DLumbOPj`Q51;Afxfw{+k*E4W@S*nStv11Sf+TQQ`ioC=khcnDFZm#>j)g zyih>sm+T!4Rgcd_L+RS0GcU|dP%C<#dM29Pn<^-jPqqObbn=wD;M)^KrmEdHp#V60=>M5cA->d>wxKNoa<^Is%UhM zGKPVF(y$!*M0-$V@(P( zIzqCU2LxV@(cktBHfy{okp!e8Wq1g+{=^+IVfQ>ooCB4#PGH7s>0CzYX>GbPdqBdI z{&QcUcIY`ZbmNxO;a)}~aMzAhK;H`)d@@cB`xutfvuys%L^RP2xnit7@J;|WL zG1H+TSmpstsE&-Mr_HR^ZSd|bdor6zqKOzP0qsbc0UgLRuHxWyz3zjA0sKBMGq14{ zL#yP5QFW7xcw4y#S8*T^nwrgQ-?GOnZt@t6;Z^J6;-+Fz9hJ!btxbB)=J;z%YTZQ0 z%fk^JM&fopL1(w~Yesx+gHy)TFoT96=}4egE76FDn_cG)M=@lx5GZ;_M&Kr9RvPU^ zG1S?UUOL3XO!rH9|SFvW>}Mi~}8h z0GU%&)vW6Fzm#1)@+CBgNvlFYIyf1?i+t|+ZC#r6=j*yhPP`5}dhYc9`ER|_5iZK3 zck}BzrpMTQcy!1I0vLNYPqRs%el(9l@TGmHN+sL3XT(EX&URaR?kM{z%juBE(U4tg za)>Cr7BwM?+@PA%IPQ%-`HelG1sj(#bxBWL0lYi1?Jl>wm6Ry5)MneW?l++&hAOT- z$mTAd2fBzjjn}t7ARv%6IQ)oR{bJH8+>PwhTL1bR(H&zlwksgc)44lup-dil0Fh)|r62AV`Nh~;B* z%4gC0zL68|5B)yYK3iH!lJAb7J)23)#yWe;Z5DD<-1g`>-%|`9*GrS*RCxBvV4|gJ z2W6~Sk}6hF)i4^i%T#y>kio8G#LjBXA@lZ|m7BUpUg)Y#d*^0ScyGF)U#gqY=>#Ek zWaXAnbY?uVT*ZLs-O+OdQ>@KaF_aZ06hDk?J2U1fg$<`A=@XbY zL1n`i+MBbXky3Rt=}+_?N-wRd0|W73-nG#Z$=VQuzKoW0IQt_-_n4I^sf z6li@MAvzQe{6l0ip&^)K^b%ovMtNOMj!9o+HgAo4m*y}F(mYoSD!E|2X!HF^#HRQx z%$In7E>8zgnl);6zR5I}5+G{G6~8ngbhdSX_!7d}ZwfU;xt5NAP-3w(MFo; zF=Ac7V|)vm?5CqeAH^|Sw)zZ1{W>IRVkgW4j(mAoFU>sC$_Cpn7j$ov#`y0x;h24t zsn>@4f)P5;kvV9kO-3E5Oh+5sbI7+ju-u=phif1oeti16oDT%i@3hx;-! z9t0I-sV?R|0wyQ6Os_3_H=c9&yj;_08ML@yk={P`Y==E<$OfWW6S&s)z+&?0?i*5y zaQbYQcEDJVxVz9}WEr4m}B!PArCrl*sy&jzu4*cwC-#nmbyXSO)YB-TSW z51Lq3lWed5s>qJCq0={c_9um+ZW8uF+{L*vq~R`_^jio{!WcXf?ls!E8@&ko9lkYF z)m^&2_(FQN5384ixNVMunXqgQ2%{NUB(y!8KmVzK_P~VUOfAnhz@YJ)h)7zXUd-=O z4S_5ufr;sR$vH_mLgn*Wq|BNR8ON^0MdRESgJ$S;| z3Ycqwd;Ma3IV&i{!Z^*})qi`0a7I*)?Sk|aq&EZu`Jzfu$^`pwy_$)NM!T(ZL-vd^ zYEESrvKb*3I+wS*bfqV?ZA>zBfLPER7aB4K@gk@x4(hpV`-sf7!W>k@&V;JFe6rEXNYZ9chA3;oV( z4PctBS2ClpGu`N0m381_bzHYSbyBd5Yise`6f3`exyDHp&H0Pt6mmaqWX1sLbRbH)WnfF5bH8 z16RlVx1_!kI1#%JU{Z812}0ZJ=DR|C9o}_TZ7lVR87cg7xx$0MH-KphRE>C$R5Uh< zTe8bk@Q<;L38$WvCinK>Am##F`JRWa_y>m8hpXeRpPKs;!13xRe(BaHJR-Bs z!x{D<#w7A_I3m2j*V*0`MZB$tHQx~~tz+H|42F7aw1~om&yPDrZe$(XwJ zea%K?d@^=wlAa{8HS)y|hA`=7G$!L}HN~{(bai#_j#QAal3VPD#PQW~weew|DmQiN zY-!^NX)vAZsDti#cz%2J0+neBTcYZ(tS?W;RCkqFs!lf^bjSv4DR^9( z_I9VWK7l*K^#Tvt4A%<`SD9C=*z?jDdohh8euNai@$|*$9#-t`6XDnOH~GwW*s=6S zU_rKDi!F*xinp`3Eu*SkawOv!XThVxvfa7VoZ(xjLO3a<_4F0I^yHA209YyeN`ypH zUohYE3O)Oq)0s8niqgjtx;mu%;XPZJ68&Ehw}-%I){EB z(ZfX;<;9F(w75rQUx>%msu6_>*s5?tJ2TStP$rv!cCkw63Pm|KYRL`E+Fu9;yDKL| ztNye*g0*lQ=rk5ywQL`%45R2A?8DTMtyq5_O8FF}EB5oB7NQj�JqKW$d;{{lK`> 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ⅅfBMuM%%C}<>5uSM@HJkIoHvKU` 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

vCdC8ZV#CJ&KOK}ktw_or;`2-pSt6lr^<4{7 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�gSt>Dxc#N}_nzxpJf!>IlxEhK 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 HKmHXJX_))81WCjbrLI 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�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%0A;Ja?ePRJ^3XEJlHXf9#9ae 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 y!5cS~hC#(d@0df}IP8OsU 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