Skip to content

Commit 22f8395

Browse files
authored
V310 (#207)
1 parent 426b6c9 commit 22f8395

File tree

118 files changed

+12331
-1278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+12331
-1278
lines changed

.github/ISSUE_TEMPLATE/bug-report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ If applicable, add screenshots to help explain your problem.
2525
**Environment (please complete the following information):**
2626
- Arch: [e.g. aarch64 or x86_64]
2727
- OS: [e.g. Linux]
28-
- Framework Version [e.g. 2.1.0]
28+
- Framework Version [e.g. 3.1.0]
2929
- Number of CPU or (GOMAXPROCS value)
3030

3131
**Additional context**

.github/images/kaspersky.png

-4.12 KB
Binary file not shown.

.github/images/lilithgames.png

-3.78 KB
Binary file not shown.

.github/images/ringcentral.png

-2.83 KB
Binary file not shown.

README.md

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ To inspect the node, network stack, running applications, and processes, you can
4747
To install the Observer tool, you need to have the Go compiler version 1.20 or higher. Run the following command:
4848

4949
```
50-
$ go install ergo.services/tools/observer@latest
50+
$ go install ergo.tools/observer@latest
5151
```
5252

5353
You can also embed the [Observer application](https://docs.ergo.services/extra-library/applications/observer) into your node. To see it in action, see example `demo` at https://github.com/ergo-services/examples. For more information https://docs.ergo.services/tools/observer
@@ -61,7 +61,7 @@ For a quick start, use the [`ergo`](https://docs.ergo.services/tools/ergo) tool
6161
To install use the following command:
6262

6363
```
64-
$ go install ergo.services/tools/ergo@latest
64+
$ go install ergo.tools/ergo@latest
6565
```
6666

6767
Now, you can create your project with just one command. Here is example:
@@ -121,7 +121,7 @@ Since we included Observer application, open http://localhost:9911 to inspect yo
121121

122122
### Erlang support ###
123123

124-
Starting from version 3.0.0, support for the Erlang network stack has been moved to a separate module and is distributed under the BSL 1.1 license - https://github.com/ergo-services/proto. You can find detailed information on using this module in the documentation at https://docs.ergo.services/extra-library/network-protocols/erlang.
124+
Starting from version 3.0.0, support for the Erlang network stack has been moved to a separate module - https://github.com/ergo-services/proto. Version 3.0 was distributed under the BSL 1.1 license, but starting from version 3.1 it is available under the MIT license. You can find detailed information on using this module in the documentation at https://docs.ergo.services/extra-library/network-protocols/erlang.
125125

126126
### Requirements ###
127127

@@ -131,23 +131,35 @@ Starting from version 3.0.0, support for the Erlang network stack has been moved
131131

132132
Fully detailed changelog see in the [ChangeLog](CHANGELOG.md) file.
133133

134-
#### [v3.0.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.300) 2024-09-04 [tag version v1.999.300] ####
135-
136-
This version marks a significant milestone in the evolution of the Ergo Framework. The framework's design has been completely overhauled, and this version was built from the ground up. It includes:
137-
138-
- Significant API Improvements: The `gen.Process`, `gen.Node`, and `gen.Network` interfaces have been enhanced with numerous convenient methods.
139-
- A New Network Stack: This version introduces a completely new network stack for improved performance and flexibility. See https://github.com/ergo-services/benchmarks for the details
140-
141-
Alongside the release of Ergo Framework 3.0.0, new tools and an additional components library are also introduced:
142-
143-
- Tools (observer, saturn) https://github.com/ergo-services/tools
144-
- Loggers (rotate, colored) - https://github.com/ergo-services/logger
145-
- Meta (websocket) - https://github.com/ergo-services/meta
146-
- Application (observer) - https://github.com/ergo-services/application
147-
- Registrar (client Saturn) - https://github.com/ergo-services/registrar
148-
- Proto (erlang23) - https://github.com/ergo-services/proto
149-
150-
Finally, we've published comprehensive documentation for the framework, providing detailed guides to assist you in leveraging all the capabilities of Ergo Framework effectively. Its available at https://docs.ergo.services.
134+
#### [v3.1.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.310) 2025-09-04 [tag version v1.999.310] ####
135+
136+
**New Features**
137+
- **Cron Scheduler**: New `gen.Cron` interface enables scheduling tasks with cron expressions, supporting second-level precision for precise task execution. See https://docs.ergo.services/basics/cron
138+
- **Port Meta Process**: New `meta.Port` allows spawning and managing external OS processes with bidirectional communication through stdin/stdout/stderr. See https://docs.ergo.services/meta-processes/port, example https://github.com/ergo-services/examples/port
139+
- **Unit Testing Framework**: Comprehensive testing library (`testing/unit`) provides isolated actor testing with event capture and validation capabilities. See https://docs.ergo.services/testing/unit
140+
141+
**Enhancements**
142+
- **Enhanced Logging**: Default logger now supports JSON output format with structured fields, improving observability and log processing
143+
- **Environment Management**: Added `gen.Process.EnvDefault()` and `gen.Node.EnvDefault()` methods
144+
- **Logger Fields**: Added `gen.Log.PushFields()` and `gen.Log.PopFields()` for contextual logging
145+
- **EDF Protocol**: Added support for `encoding.BinaryMarshaler/BinaryUnmarshaler` interfaces
146+
- **Performance**: Multiple optimizations across message handling and network operations
147+
148+
**Critical Bug Fixes**
149+
- **Node Shutdown**: Fixed race condition causing "close of closed channel" panic during graceful shutdown
150+
- **Supervisor Issues**: Fixed OFO supervisor child termination (#213), restart intensity calculation with millisecond precision, and duplicate Terminate callbacks
151+
- **SIGTERM Handling**: Improved graceful shutdown behavior and SOFO supervisor cleanup
152+
- **EDF Codec**: Fixed nil slice/map decoding issues
153+
- **Local Registrar**: Improved resolver detection for service discovery
154+
155+
**Extra Library**
156+
- **Module Independence**: All extra library modules (Logger, Meta, Registrar, etc...) are now independent Go modules with dependency management
157+
- **Tools Domain**: All tools moved to dedicated `ergo.tools` domain for better organization and distribution
158+
- **Proto**: `erlang23` (Erlang network stack implementation) changed from BSL 1.1 to MIT license for broader adoption and commercial use
159+
- **Registrar**: New etcd registrar implementation with distributed service discovery, hierarchical configuration, real-time cluster events. See https://docs.ergo.services/extra-library/registrars/etcd-client and example https://github.com/ergo-services/examples/docker
160+
- **Logger**: Added LogField support in colored logger, banner functionality, and fixed options handling. See https://docs.ergo.services/extra-library/loggers
161+
- **Application**: Observer application enhanced with new Applications page, Cron job details, and UI fixes. See https://docs.ergo.services/extra-library/applications/observer
162+
- **Benchmarks**: New serialization benchmarks comparing EDF vs Gob vs Protobuf performance, expanded test suite coverage. See https://github.com/ergo-services/benchmarks
151163

152164
### Development and debugging ###
153165

@@ -163,7 +175,7 @@ To run tests with cleaned test cache:
163175
```
164176
go vet
165177
go clean -testcache
166-
go test -v ./tests/...
178+
go test -v ./testing/tests/...
167179
```
168180

169181
### Commercial support

act/README.md

Lines changed: 0 additions & 4 deletions
This file was deleted.

act/supervisor.go

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,14 @@ func (s *Supervisor) StartChild(name gen.Atom, args ...any) error {
192192
return gen.ErrNotAllowed
193193
}
194194

195-
if s.state != supStateNormal {
196-
return ErrSupervisorStrategyActive
197-
}
198-
199195
action, err := s.sup.childSpec(name)
200196
if err != nil {
201197
return err
202198
}
203199
if len(args) > 0 {
204200
action.spec.Args = args
205201
}
202+
206203
return s.handleAction(action)
207204
}
208205

@@ -227,10 +224,6 @@ func (s *Supervisor) EnableChild(name gen.Atom) error {
227224
return gen.ErrNotAllowed
228225
}
229226

230-
if s.state != supStateNormal {
231-
return ErrSupervisorStrategyActive
232-
}
233-
234227
action, err := s.sup.childEnable(name)
235228
if err != nil {
236229
return err
@@ -317,6 +310,7 @@ func (s *Supervisor) ProcessInit(process gen.Process, args ...any) (rr error) {
317310
if dup {
318311
return ErrSupervisorChildDuplicate
319312
}
313+
duplicate[s.Name] = true
320314
}
321315

322316
// create supervisor
@@ -561,14 +555,18 @@ func (s *Supervisor) handleAction(action supAction) error {
561555
action.spec.Options.LinkParent = true
562556

563557
if action.spec.register {
564-
pid, err = s.SpawnRegister(action.spec.Name, action.spec.Factory, action.spec.Options, action.spec.Args...)
558+
pid, err = s.SpawnRegister(
559+
action.spec.Name,
560+
action.spec.Factory,
561+
action.spec.Options,
562+
action.spec.Args...)
565563
} else {
566564
pid, err = s.Spawn(action.spec.Factory, action.spec.Options, action.spec.Args...)
567565
}
568566

569567
if err != nil {
570-
action = s.sup.childTerminated(action.spec.Name, pid, err)
571-
continue
568+
s.state = supStateNormal
569+
return err
572570
}
573571

574572
if s.handleChild {
@@ -580,16 +578,26 @@ func (s *Supervisor) handleAction(action supAction) error {
580578
continue
581579

582580
case supActionTerminateChildren:
581+
if len(action.terminate) == 0 {
582+
// no children. terminate this process
583+
return action.reason
584+
}
583585
// on disabling child spec
584586
s.state = supStateStrategy
585587
for _, pid := range action.terminate {
586-
s.SendExit(pid, action.reason)
587-
s.Log().Info("Supervisor: terminate children %s", pid)
588+
// TODO
589+
// Child is disabling if exceeded restart limits. basically we dont need
590+
// to send exit again.
591+
// Current workaround: SendExit return error if its terminated already,
592+
// so dont log misleading message
593+
if err := s.SendExit(pid, action.reason); err == nil {
594+
s.Log().Info("Supervisor: terminate children %s", pid)
595+
}
588596
}
597+
s.state = supStateNormal
589598
return nil
590599

591600
case supActionTerminate:
592-
s.behavior.Terminate(action.reason)
593601
return action.reason
594602

595603
default:
@@ -667,19 +675,26 @@ type supMessageChildTerminate struct {
667675
reason error
668676
}
669677

670-
// checkRestartIntensity returns true if exceeded
678+
// supCheckRestartIntensity returns true if exceeded
671679
func supCheckRestartIntensity(restarts []int64, period int, intensity int) ([]int64, bool) {
672-
restarts = append(restarts, time.Now().Unix())
673-
if len(restarts) < intensity {
680+
// Use milliseconds for better granularity
681+
now := time.Now().UnixMilli()
682+
restarts = append(restarts, now)
683+
if len(restarts) <= intensity {
674684
return restarts, false
675685
}
676686

677-
p := int(time.Now().Unix() - restarts[0])
678-
if p > period {
687+
// Remove old restarts outside the period window
688+
periodMillis := int64(period) * 1000
689+
for len(restarts) > 0 && now-restarts[0] > periodMillis {
679690
restarts = restarts[1:]
680-
return restarts, false
681691
}
682-
return restarts, true
692+
693+
// Check if we still exceed intensity after cleanup
694+
if len(restarts) > intensity {
695+
return restarts, true
696+
}
697+
return restarts, false
683698
}
684699

685700
func validateChildSpec(s SupervisorChildSpec) error {

act/supervisor_arfo.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ func (s *supARFO) childEnable(name gen.Atom) (supAction, error) {
402402
}
403403

404404
// it was disabled. enable it and start child process with this spec
405+
cs.disabled = false
405406

406407
action.do = supActionStartChild
407408
action.spec = *cs

act/supervisor_ofo.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ func (s *supOFO) childTerminated(name gen.Atom, pid gen.PID, reason error) supAc
311311
if cs.pid == empty {
312312
continue
313313
}
314-
action.terminate = append(action.terminate, pid)
314+
action.terminate = append(action.terminate, cs.pid)
315315
}
316316
action.do = supActionTerminateChildren
317317
action.reason = ErrSupervisorRestartsExceeded
@@ -335,6 +335,7 @@ func (s *supOFO) childEnable(name gen.Atom) (supAction, error) {
335335
}
336336

337337
// it was disabled. enable it and start child process with this spec
338+
cs.disabled = false
338339

339340
action.do = supActionStartChild
340341
action.spec = *cs

act/supervisor_sofo.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ func (s *supSOFO) childSpec(name gen.Atom) (supAction, error) {
8686
if spec.disabled {
8787
return action, ErrSupervisorChildDisabled
8888
}
89+
8990
action.do = supActionStartChild
9091
action.spec = *spec
9192
return action, nil

0 commit comments

Comments
 (0)