Skip to content

Commit 093c5d1

Browse files
authored
V220 (#110)
1 parent d9bfaba commit 093c5d1

File tree

136 files changed

+8010
-1935
lines changed

Some content is hidden

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

136 files changed

+8010
-1935
lines changed

.github/images/observer.gif

-552 KB
Binary file not shown.

ChangeLog.md

+63
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,69 @@ All notable changes to this project will be documented in this file.
44
This format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
#### [v2.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.220) 2022-10-18 [tag version v1.999.220] ####
8+
9+
* Introduced `gen.Web` behavior. It implements **Web API Gateway pattern** is also sometimes known as the "Backend For Frontend" (BFF). See example [examples/genweb](examples/genweb)
10+
* Introduced `gen.TCP` behavior - **socket acceptor pool for TCP protocols**. It provides everything you need to accept TCP connections and process packets with a small code base and low latency. Here is simple example [examples/gentcp](examples/gentcp)
11+
* Introduced `gen.UDP` - the same as `gen.TCP`, but for UDP protocols. Example is here [examples/genudp](examples/genudp)
12+
* Introduced **Events**. This is a simple pub/sub feature within a node - any `gen.Process` can become a producer by registering a new event `gen.Event` using method `gen.Process.RegisterEvent`, while the others can subscribe to these events using `gen.Process.MonitorEvent`. Subscriber process will also receive `gen.MessageEventDown` if a producer process went down (terminated). This feature behaves in a monitor manner but only works within a node. You may also want to subscribe to a system event - `node.EventNetwork` to receive event notification on connect/disconnect any peers.
13+
* Introduced **Cloud Client** - allows connecting to the cloud platform [https://ergo.sevices](https://ergo.services). You may want to register your email there, and we will inform you about the platform launch day
14+
* Introduced **type registration** for the ETF encoding/decoding. This feature allows you to get rid of manually decoding with `etf.TermIntoStruct` for the receiving messages. Register your type using `etf.RegisterType(...)`, and you will be receiving messages in a native type
15+
* Predefined set of errors has moved to the `lib` package
16+
* Updated `gen.ServerBehavior.HandleDirect` method (got extra argument `etf.Ref` to distinguish the requests). This change allows you to handle these requests asynchronously using method `gen.ServerProcess.Reply(...)`
17+
* Updated `node.Options`. Now it has field `Listeners` (type `node.Listener`). It allows you to start any number of listeners with custom options - `Port`, `TLS` settings, or custom `Handshake`/`Proto` interfaces
18+
* Fixed build on 32-bit arch
19+
* Fixed freezing on ARM arch #102
20+
* Fixed problem with encoding negative int8
21+
* Fixed #103 (there was an issue on interop with Elixir's GenStage)
22+
* Fixed node stuck on start if it uses the name which is already taken in EPMD
23+
* Fixed incorrect `gen.ProcessOptions.Context` handling
24+
25+
26+
#### [v2.1.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.210) 2022-04-19 [tag version v1.999.210] ####
27+
28+
* Introduced **compression feature** support. Here are new methods and options to manage this feature:
29+
- `gen.Process`:
30+
- `SetCompression(enable bool)`, `Compression() bool`
31+
- `SetCompressionLevel(level int) bool`, `CompressionLevel() int`
32+
- `SetCompressionThreshold(threshold int) bool`, `CompressionThreshold() int` messages smaller than the threshold will be sent with no compression. The default compression threshold is 1024 bytes.
33+
- `node.Options`:
34+
- `Compression` these settings are used as defaults for the spawning processes
35+
- this feature will be ignored if the receiver is running on either the Erlang or Elixir node
36+
* Introduced **proxy feature** support **with end-to-end encryption**.
37+
- `node.Node` new methods:
38+
- `AddProxyRoute(...)`, `RemoveProxyRoute(...)`
39+
- `ProxyRoute(...)`, `ProxyRoutes()`
40+
- `NodesIndirect()` returns list of connected nodes via proxy connection
41+
- `node.Options`:
42+
- `Proxy` for configuring proxy settings
43+
- includes support (over the proxy connection): compression, fragmentation, link/monitor process, monitor node
44+
- example [examples/proxy](examples/proxy).
45+
- this feature is not available for the Erlang/Elixir nodes
46+
* Introduced **behavior `gen.Raft`**. It's improved implementation of [Raft consensus algorithm](https://raft.github.io). The key improvement is using quorum under the hood to manage the leader election process and make the Raft cluster more reliable. This implementation supports quorums of 3, 5, 7, 9, or 11 quorum members. Here is an example of this feature [examples/genraft](examples/genraft).
47+
* Introduced **interfaces to customize network layer**
48+
- `Resolver` to replace EPMD routines with your solution (e.g., ZooKeeper or any other service registrar)
49+
- `Handshake` allows customizing authorization/authentication process
50+
- `Proto` provides the way to implement proprietary protocols (e.g., IoT area)
51+
* Other new features:
52+
- `gen.Process` new methods:
53+
- `NodeUptime()`, `NodeName()`, `NodeStop()`
54+
- `gen.ServerProcess` new method:
55+
- `MessageCounter()` shows how many messages have been handled by the `gen.Server` callbacks
56+
- `gen.ProcessOptions` new option:
57+
- `ProcessFallback` allows forward messages to the fallback process if the process mailbox is full. Forwarded messages are wrapped into `gen.MessageFallback` struct. Related to issue #96.
58+
- `gen.SupervisorChildSpec` and `gen.ApplicationChildSpec` got option `gen.ProcessOptions` to customize options for the spawning child processes.
59+
* Improved sending messages by etf.Pid or etf.Alias: methods `gen.Process.Send`, `gen.ServerProcess.Cast`, `gen.ServerProcess.Call` now return `node.ErrProcessIncarnation` if a message is sending to the remote process of the previous incarnation (remote node has been restarted). Making monitor on a remote process of the previous incarnation triggers sending `gen.MessageDown` with reason `incarnation`.
60+
* Introduced type `gen.EnvKey` for the environment variables
61+
* All spawned processes now have the `node.EnvKeyNode` variable to get access to the `node.Node` value.
62+
* **Improved performance** of local messaging (**up to 8 times** for some cases)
63+
* **Important** `node.Options` has changed. Make sure to adjust your code.
64+
* Fixed issue #89 (incorrect handling of Call requests)
65+
* Fixed issues #87, #88 and #93 (closing network socket)
66+
* Fixed issue #96 (silently drops message if process mailbox is full)
67+
* Updated minimal requirement of Golang version to 1.17 (go.mod)
68+
* We still keep the rule **Zero Dependencies**
69+
770
#### [v2.0.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.200) 2021-10-12 [tag version v1.999.200] ####
871

972
* Added support of Erlang/OTP 24 (including [Alias](https://blog.erlang.org/My-OTP-24-Highlights/#eep-53-process-aliases) feature and [Remote Spawn](https://blog.erlang.org/OTP-23-Highlights/#distributed-spawn-and-the-new-erpc-module) introduced in Erlang/OTP 23)

README.md

+31-80
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
<!--[![Gitbook Documentation](https://img.shields.io/badge/GitBook-Documentation-f37f40?style=plastic&logo=gitbook&logoColor=white&style=flat)](https://docs.ergo.services) -->
44
[![GoDoc](https://pkg.go.dev/badge/ergo-services/ergo)](https://pkg.go.dev/github.com/ergo-services/ergo)
5-
[![Build Status](https://img.shields.io/github/workflow/status/ergo-services/ergo/TestLinuxWindowsMacOS)](https://github.com/ergo-services/ergo/actions/)
5+
[![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
66
[![Telegram Community](https://img.shields.io/badge/Telegram-Community-blue?style=flat&logo=telegram)](https://t.me/ergo_services)
77
[![Discord Community](https://img.shields.io/badge/Discord-Community-5865F2?style=flat&logo=discord&logoColor=white)](https://discord.gg/sdscxKGV62)
88
[![Twitter](https://img.shields.io/badge/Twitter-ergo__services-1DA1F2?style=flat&logo=twitter&logoColor=white)](https://twitter.com/ergo_services)
9-
[![MIT license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
109

1110
Technologies and design patterns of Erlang/OTP have been proven over the years. Now in Golang.
1211
Up to x5 times faster than original Erlang/OTP in terms of network messaging.
@@ -37,7 +36,7 @@ The goal of this project is to leverage Erlang/OTP experience with Golang perfor
3736
* Transient
3837
* `gen.Stage` behavior support (originated from Elixir's [GenStage](https://hexdocs.pm/gen_stage/GenStage.html)). This is abstraction built on top of `gen.Server` to provide a simple way to create a distributed Producer/Consumer architecture, while automatically managing the concept of backpressure. This implementation is fully compatible with Elixir's GenStage. Example is here [examples/genstage](examples/genstage) or just run `go run ./examples/genstage` to see it in action
3938
* `gen.Saga` behavior support. It implements Saga design pattern - a sequence of transactions that updates each service state and publishes the result (or cancels the transaction or triggers the next transaction step). `gen.Saga` also provides a feature of interim results (can be used as transaction progress or as a part of pipeline processing), time deadline (to limit transaction lifespan), two-phase commit (to make distributed transaction atomic). Here is example [examples/gensaga](examples/gensaga).
40-
* `gen.Raft` behavior support. It's improved implementation of [Raft consensus algorithm](https://raft.github.io). The key improvement is using quorum under the hood to manage the leader election process and make the Raft cluster more reliable. This implementation supports quorums of 3, 5, 7, 9, or 11 quorum members. Here is an example of this feature [examples/raft](examples/raft).
39+
* `gen.Raft` behavior support. It's improved implementation of [Raft consensus algorithm](https://raft.github.io). The key improvement is using quorum under the hood to manage the leader election process and make the Raft cluster more reliable. This implementation supports quorums of 3, 5, 7, 9, or 11 quorum members. Here is an example of this feature [examples/genraft](examples/genraft).
4140
* Connect to (accept connection from) any Erlang/Elixir node within a cluster
4241
* Making sync request `ServerProcess.Call`, async - `ServerProcess.Cast` or `Process.Send` in fashion of `gen_server:call`, `gen_server:cast`, `erlang:send` accordingly
4342
* Monitor processes/nodes, local/remote
@@ -64,50 +63,23 @@ Golang introduced [v2 rule](https://go.dev/blog/v2-go-modules) a while ago to so
6463

6564
Here are the changes of latest release. For more details see the [ChangeLog](ChangeLog.md)
6665

67-
#### [v2.1.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.210) 2022-04-19 [tag version v1.999.210] ####
68-
69-
* Introduced **compression feature** support. Here are new methods and options to manage this feature:
70-
- `gen.Process`:
71-
- `SetCompression(enable bool)`, `Compression() bool`
72-
- `SetCompressionLevel(level int) bool`, `CompressionLevel() int`
73-
- `SetCompressionThreshold(threshold int) bool`, `CompressionThreshold() int` messages smaller than the threshold will be sent with no compression. The default compression threshold is 1024 bytes.
74-
- `node.Options`:
75-
- `Compression` these settings are used as defaults for the spawning processes
76-
- this feature will be ignored if the receiver is running on either the Erlang or Elixir node
77-
* Introduced **proxy feature** support **with end-to-end encryption**.
78-
- `node.Node` new methods:
79-
- `AddProxyRoute(...)`, `RemoveProxyRoute(...)`
80-
- `ProxyRoute(...)`, `ProxyRoutes()`
81-
- `NodesIndirect()` returns list of connected nodes via proxy connection
82-
- `node.Options`:
83-
- `Proxy` for configuring proxy settings
84-
- includes support (over the proxy connection): compression, fragmentation, link/monitor process, monitor node
85-
- example [examples/proxy](examples/proxy).
86-
- this feature is not available for the Erlang/Elixir nodes
87-
* Introduced **behavior `gen.Raft`**. It's improved implementation of [Raft consensus algorithm](https://raft.github.io). The key improvement is using quorum under the hood to manage the leader election process and make the Raft cluster more reliable. This implementation supports quorums of 3, 5, 7, 9, or 11 quorum members. Here is an example of this feature [examples/raft](examples/raft).
88-
* Introduced **interfaces to customize network layer**
89-
- `Resolver` to replace EPMD routines with your solution (e.g., ZooKeeper or any other service registrar)
90-
- `Handshake` allows customizing authorization/authentication process
91-
- `Proto` provides the way to implement proprietary protocols (e.g., IoT area)
92-
* Other new features:
93-
- `gen.Process` new methods:
94-
- `NodeUptime()`, `NodeName()`, `NodeStop()`
95-
- `gen.ServerProcess` new method:
96-
- `MessageCounter()` shows how many messages have been handled by the `gen.Server` callbacks
97-
- `gen.ProcessOptions` new option:
98-
- `ProcessFallback` allows forward messages to the fallback process if the process mailbox is full. Forwarded messages are wrapped into `gen.MessageFallback` struct. Related to issue #96.
99-
- `gen.SupervisorChildSpec` and `gen.ApplicationChildSpec` got option `gen.ProcessOptions` to customize options for the spawning child processes.
100-
* Improved sending messages by etf.Pid or etf.Alias: methods `gen.Process.Send`, `gen.ServerProcess.Cast`, `gen.ServerProcess.Call` now return `node.ErrProcessIncarnation` if a message is sending to the remote process of the previous incarnation (remote node has been restarted). Making monitor on a remote process of the previous incarnation triggers sending `gen.MessageDown` with reason `incarnation`.
101-
* Introduced type `gen.EnvKey` for the environment variables
102-
* All spawned processes now have the `node.EnvKeyNode` variable to get access to the `node.Node` value.
103-
* **Improved performance** of local messaging (**up to 8 times** for some cases)
104-
* **Important** `node.Options` has changed. Make sure to adjust your code.
105-
* Fixed issue #89 (incorrect handling of Call requests)
106-
* Fixed issues #87, #88 and #93 (closing network socket)
107-
* Fixed issue #96 (silently drops message if process mailbox is full)
108-
* Updated minimal requirement of Golang version to 1.17 (go.mod)
109-
* We still keep the rule **Zero Dependencies**
110-
66+
#### [v2.2.0](https://github.com/ergo-services/ergo/releases/tag/v1.999.220) 2022-10-18 [tag version v1.999.220] ####
67+
68+
* Introduced `gen.Web` behavior. It implements **Web API Gateway pattern** is also sometimes known as the "Backend For Frontend" (BFF). See example [examples/genweb](examples/genweb)
69+
* Introduced `gen.TCP` behavior - **socket acceptor pool for TCP protocols**. It provides everything you need to accept TCP connections and process packets with a small code base and low latency. Here is simple example [examples/gentcp](examples/gentcp)
70+
* Introduced `gen.UDP` - the same as `gen.TCP`, but for UDP protocols. Example is here [examples/genudp](examples/genudp)
71+
* Introduced **Events**. This is a simple pub/sub feature within a node - any `gen.Process` can become a producer by registering a new event `gen.Event` using method `gen.Process.RegisterEvent`, while the others can subscribe to these events using `gen.Process.MonitorEvent`. Subscriber process will also receive `gen.MessageEventDown` if a producer process went down (terminated). This feature behaves in a monitor manner but only works within a node. You may also want to subscribe to a system event - `node.EventNetwork` to receive event notification on connect/disconnect any peers. Here is simple example of this feature [examples/events](examples/events)
72+
* Introduced **Cloud Client** - allows connecting to the cloud platform [https://ergo.sevices](https://ergo.services). You may want to register your email there, and we will inform you about the platform launch day
73+
* Introduced **type registration** for the ETF encoding/decoding. This feature allows you to get rid of manually decoding with `etf.TermIntoStruct` for the receiving messages. Register your type using `etf.RegisterType(...)`, and you will be receiving messages in a native type
74+
* Predefined set of errors has moved to the `lib` package
75+
* Updated `gen.ServerBehavior.HandleDirect` method (got extra argument `etf.Ref` to distinguish the requests). This change allows you to handle these requests asynchronously using method `gen.ServerProcess.Reply(...)`
76+
* Updated `node.Options`. Now it has field `Listeners` (type `node.Listener`). It allows you to start any number of listeners with custom options - `Port`, `TLS` settings, or custom `Handshake`/`Proto` interfaces
77+
* Fixed build on 32-bit arch
78+
* Fixed freezing on ARM arch #102
79+
* Fixed problem with encoding negative int8
80+
* Fixed #103 (there was an issue on interop with Elixir's GenStage)
81+
* Fixed node stuck on start if it uses the name which is already taken in EPMD
82+
* Fixed incorrect `gen.ProcessOptions.Context` handling
11183

11284
### Benchmarks ###
11385

@@ -183,17 +155,9 @@ sources of these benchmarks are [here](https://github.com/halturin/ergobenchmark
183155

184156
The one thing that makes embedded EPMD different is the behavior of handling connection hangs - if ergo' node is running as an EPMD client and lost connection, it tries either to run its own embedded EPMD service or to restore the lost connection.
185157

186-
### Observer ###
187-
188-
It's a standard Erlang tool. Observer is a graphical tool for observing the characteristics of Erlang systems. The tool Observer displays system information, application supervisor trees, process information.
189-
190-
Here you can see this feature in action using one of the [examples](examples/):
191-
192-
![observer demo](.github/images/observer.gif)
193-
194158
### Examples ###
195159

196-
Code below is a simple implementation of gen.Server pattern [examples/simple](examples/simple)
160+
Code below is a simple implementation of gen.Server pattern [examples/genserver](examples/genserver)
197161

198162
```golang
199163
package main
@@ -202,13 +166,10 @@ import (
202166
"fmt"
203167
"time"
204168

205-
"github.com/ergo-services/ergo"
206169
"github.com/ergo-services/ergo/etf"
207170
"github.com/ergo-services/ergo/gen"
208-
"github.com/ergo-services/ergo/node"
209171
)
210172

211-
// simple implementation of Server
212173
type simple struct {
213174
gen.Server
214175
}
@@ -219,27 +180,12 @@ func (s *simple) HandleInfo(process *gen.ServerProcess, message etf.Term) gen.Se
219180
if value > 104 {
220181
return gen.ServerStatusStop
221182
}
222-
// sending message with delay
223-
process.SendAfter(process.Self(), value+1, time.Duration(1*time.Second))
183+
// sending message with delay 1 second
184+
fmt.Println("increase this value by 1 and send it to itself again")
185+
process.SendAfter(process.Self(), value+1, time.Second)
224186
return gen.ServerStatusOK
225187
}
226188

227-
func main() {
228-
// create a new node
229-
node, _ := ergo.StartNode("node@localhost", "cookies", node.Options{})
230-
231-
// spawn a new process of gen.Server
232-
process, _ := node.Spawn("gs1", gen.ProcessOptions{}, &simple{})
233-
234-
// send a message to itself
235-
process.Send(process.Self(), 100)
236-
237-
// wait for the process termination.
238-
process.Wait()
239-
fmt.Println("exited")
240-
node.Stop()
241-
}
242-
243189
```
244190

245191
here is output of this code
@@ -262,9 +208,14 @@ See `examples/` for more details
262208
* [gen.Server](examples/genserver)
263209
* [gen.Stage](examples/genstage)
264210
* [gen.Saga](examples/gensaga)
265-
* [gen.Demo](examples/gendemo)
266-
* [Node with TLS](examples/nodetls)
267-
* [Node with HTTP server](examples/http)
211+
* [gen.Raft](examples/genraft)
212+
* [gen.Custom](examples/gencustom)
213+
* [gen.Web](examples/genweb)
214+
* [gen.TCP](examples/gentcp)
215+
* [gen.UDP](examples/genudp)
216+
* [events](examples/events)
217+
* [erlang](examples/erlang)
218+
* [proxy](examples/proxy)
268219

269220
### Elixir Phoenix Users ###
270221

0 commit comments

Comments
 (0)