Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1 Refactoring - phase 1 #50

Merged
merged 40 commits into from
Dec 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d655654
Update Readme to use active Process() instead of reactive handlers
trustmaster Oct 30, 2018
aa71fbf
Exclude non-component files from build while rewriting
trustmaster Nov 3, 2018
b33a469
Disable the old component test cases
trustmaster Nov 3, 2018
f7d9d06
Hello new component world
trustmaster Nov 8, 2018
252b3c6
Add test for long running process
trustmaster Nov 8, 2018
ef2f670
Add a more sophisticated test
trustmaster Nov 10, 2018
d08b68e
Simplify component run code
trustmaster Nov 10, 2018
3835a3a
Add .gitignore
trustmaster Nov 10, 2018
41f0c91
Move input close count logic to InputGuard helper
trustmaster Nov 10, 2018
812df4a
Try graph code from scratch
trustmaster Nov 11, 2018
75eb9c3
Start refactoring network structs and Add methods
trustmaster Nov 12, 2018
ccee26a
Delete new graph.go, stick to refactoring network.go
trustmaster Nov 12, 2018
f34c882
Make network.go buildable
trustmaster Nov 12, 2018
ec908b7
Start refactoring Graph.Connect()
trustmaster Nov 13, 2018
e6545a8
Fix build errors
trustmaster Nov 15, 2018
945ce7a
Extract port getting logic to a function
trustmaster Nov 16, 2018
9517973
Extract channel type validation
trustmaster Nov 16, 2018
94b60cc
Complete refactoring Connect() method
trustmaster Nov 17, 2018
b500fd7
Rename network.go -> graph.go
trustmaster Nov 17, 2018
1bec68c
Move connection logic to a separate file
trustmaster Nov 17, 2018
c727edd
Move graph ports logic to a separate file
trustmaster Nov 17, 2018
9667611
Fix linter errors in protocol.go
trustmaster Nov 17, 2018
706a2ca
Move IIP to a separate file
trustmaster Nov 17, 2018
3b46dd4
Add basic code to run a graph
trustmaster Nov 18, 2018
477b9d6
Update port mapping code
trustmaster Nov 18, 2018
9bec1df
Update port setting code
trustmaster Nov 18, 2018
4093aff
Rename connection file as it belongs to graph
trustmaster Nov 18, 2018
28b4214
Get the first passing graph test
trustmaster Nov 19, 2018
96fdb09
Remove irrelevant functions
trustmaster Nov 24, 2018
3e0f146
Add test for adding invalid process type
trustmaster Nov 24, 2018
03267bf
Improve Graph.Remove()
trustmaster Nov 24, 2018
a5cf875
Add Travis CI
trustmaster Nov 30, 2018
e18b1b0
Update Readme
trustmaster Nov 30, 2018
ae98c88
Fix formatting
trustmaster Nov 30, 2018
5265ef1
Update code sending IIPs
trustmaster Dec 5, 2018
1a56b07
Add a failing test for IIP
trustmaster Dec 5, 2018
939fc3c
Add sending of the IIP
trustmaster Dec 6, 2018
5fcb888
Fix guarding of closed ports
trustmaster Dec 6, 2018
3c9fe5b
Update branch warning
trustmaster Dec 6, 2018
c1a4aa1
Remove old net tests
trustmaster Dec 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

.vscode

# Editor files
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: go

go:
- "1.x"
76 changes: 42 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# GoFlow - Dataflow and Flow-based programming library for Go (golang)

This is quite a minimalistic implementation of [Flow-based programming](http://en.wikipedia.org/wiki/Flow-based_programming) and several other concurrent models in Go programming language that aims at designing applications as graphs of components which react to data that flows through the graph.
[![Build Status](https://travis-ci.com/trustmaster/goflow.svg?branch=master)](https://travis-ci.com/trustmaster/goflow)

### _Status of this branch_

_Warning: you are currently on v1 branch of GoFlow. v1 is a revisit and refactoring of the original GoFlow code which remained almost unchanged for 7 years. This branch is deep *in progress*, no stability guaranteed. API also may change._

- _[More information on v1](https://github.com/trustmaster/goflow/issues/49)_
- _[Take me back to v0](https://github.com/trustmaster/goflow/tree/v0)_

_If your code depends on the old implementation, you can build it using [release 0.1](https://github.com/trustmaster/goflow/releases/tag/0.1)._

--

This a lean and opinionated implementation of [Flow-based programming](http://en.wikipedia.org/wiki/Flow-based_programming) in Go sthat aims at designing applications as graphs of components which react to data that flows through the graph.

The main properties of the proposed model are:

Expand All @@ -12,7 +25,7 @@ The main properties of the proposed model are:

## Getting started

Current version of the library requires a latest stable Go release. If you don't have the Go compiler installed, read the official [Go install guide](http://golang.org/doc/install).
If you don't have the Go compiler installed, read the official [Go install guide](http://golang.org/doc/install).

Use go tool to install the package in your packages tree:

Expand Down Expand Up @@ -42,43 +55,42 @@ import (
"github.com/trustmaster/goflow"
)

// A component that generates greetings
// Greeter sends greetings
type Greeter struct {
flow.Component // component "superclass" embedded
Name <-chan string // input port
Res chan<- string // output port
}

// Reaction to a new name input
func (g *Greeter) OnName(name string) {
greeting := fmt.Sprintf("Hello, %s!", name)
// send the greeting to the output port
g.Res <- greeting
// Process incoming data
func (c *Greeter) Process() {
// Keep reading incoming packets
for name := range c.Name {
greeting := fmt.Sprintf("Hello, %s!", name)
// Send the greeting to the output port
c.Res <- greeting
}
close(c.Res)
}

// A component that prints its input on screen
// Printer prints its input on screen
type Printer struct {
flow.Component
Line <-chan string // inport
}

// Prints a line when it gets it
func (p *Printer) OnLine(line string) {
fmt.Println(line)
}

// Our greeting network
type GreetingApp struct {
flow.Graph // graph "superclass" embedded
// Process prints a line when it gets it
func (c *Printer) Process() {
for line := range c.Line {
fmt.Println(line)
}
close(c.Line)
}

// Graph constructor and structure definition
func NewGreetingApp() *GreetingApp {
n := new(GreetingApp) // creates the object in heap
n.InitGraphState() // allocates memory for the graph
// NewGreetingApp defines the app graph
func NewGreetingApp() *flow.Graph {
n := flow.NewGraph()
// Add processes to the network
n.Add(new(Greeter), "greeter")
n.Add(new(Printer), "printer")
n.Add("greeter", new(Greeter))
n.Add("printer", new(Printer))
// Connect them with a channel
n.Connect("greeter", "Res", "printer", "Line")
// Our net has 1 inport mapped to greeter.Name
Expand All @@ -93,21 +105,21 @@ func main() {
in := make(chan string)
net.SetInPort("In", in)
// Run the net
flow.RunNet(net)
wait := flow.Run(net)
// Now we can send some names and see what happens
in <- "John"
in <- "Boris"
in <- "Hanna"
// Close the input to shut the network down
// Send end of input
close(in)
// Wait until the app has done its job
<-net.Wait()
// Wait until the net has completed its job
<-wait
}
```

Looks a bit heavy for such a simple task but FBP is aimed at a bit more complex things than just printing on screen. So in more complex an realistic examples the infractructure pays the price.

You probably have one question left even after reading the comments in code: why do we need to wait for the finish signal? This is because flow-based world is asynchronous and while you expect things to happen in the same sequence as they are in main(), during runtime they don't necessarily follow the same order and the application might terminate before the network has done its job. To avoid this confusion we listen for a signal on network's `Wait()` channel which is closed when the network finishes its job.
You probably have one question left even after reading the comments in code: why do we need to wait for the finish signal? This is because flow-based world is asynchronous and while you expect things to happen in the same sequence as they are in main(), during runtime they don't necessarily follow the same order and the application might terminate before the network has done its job. To avoid this confusion we listen for a signal on network's `wait` channel which is sent when the network finishes its job.

## Terminology

Expand Down Expand Up @@ -144,10 +156,6 @@ Documentation for the flow package can be accessed using standard godoc tool, e.
godoc github.com/trustmaster/goflow
```

## More examples

* [GoChat](https://github.com/trustmaster/gochat), a simple chat in Go using this library

## Links

Here are related projects and resources:
Expand Down
Loading