Skip to content

Commit

Permalink
Component state (#95)
Browse files Browse the repository at this point in the history
Add component state
  • Loading branch information
hovsep authored Feb 3, 2025
1 parent 85e781f commit 0ab2e70
Show file tree
Hide file tree
Showing 38 changed files with 2,402 additions and 1,123 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.23"

- name: Install dependencies
run: go mod download

- name: Run tests
run: go test -coverprofile=coverage.txt
run: go test ./... -coverprofile=coverage.txt

- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.61

- name: Upload results to Codecov
uses: codecov/codecov-action@v4
Expand Down
20 changes: 0 additions & 20 deletions .github/workflows/qodana_code_quality.yml

This file was deleted.

5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
test:
go test ./...

lint:
golangci-lint run ./...
83 changes: 41 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,54 +31,53 @@ Learn more in [documentation](https://github.com/hovsep/fmesh/wiki)


<h2>Example:</h2>

```go
fm := fmesh.New("hello world").
WithComponents(
component.New("concat").
WithInputs("i1", "i2").
WithOutputs("res").
WithActivationFunc(func(inputs *port.Collection, outputs *port.Collection) error {
word1 := inputs.ByName("i1").FirstSignalPayloadOrDefault("").(string)
word2 := inputs.ByName("i2").FirstSignalPayloadOrDefault("").(string)

outputs.ByName("res").PutSignals(signal.New(word1 + word2))
return nil
}),
component.New("case").
WithInputs("i1").
WithOutputs("res").
WithActivationFunc(func(inputs *port.Collection, outputs *port.Collection) error {
inputString := inputs.ByName("i1").FirstSignalPayloadOrDefault("").(string)
t.Run("readme test", func(t *testing.T) {
fm := fmesh.New("hello world").
WithComponents(
component.New("concat").
WithInputs("i1", "i2").
WithOutputs("res").
WithActivationFunc(func(this *component.Component) error {
word1 := this.InputByName("i1").FirstSignalPayloadOrDefault("").(string)
word2 := this.InputByName("i2").FirstSignalPayloadOrDefault("").(string)
this.OutputByName("res").PutSignals(signal.New(word1 + word2))
return nil
}),
component.New("case").
WithInputs("i1").
WithOutputs("res").
WithActivationFunc(func(this *component.Component) error {
inputString := this.InputByName("i1").FirstSignalPayloadOrDefault("").(string)
this.OutputByName("res").PutSignals(signal.New(strings.ToTitle(inputString)))
return nil
})).
WithConfig(fmesh.Config{
ErrorHandlingStrategy: fmesh.StopOnFirstErrorOrPanic,
CyclesLimit: 10,
})

outputs.ByName("res").PutSignals(signal.New(strings.ToTitle(inputString)))
return nil
})).
WithConfig(fmesh.Config{
ErrorHandlingStrategy: fmesh.StopOnFirstErrorOrPanic,
CyclesLimit: 10,
})
fm.Components().ByName("concat").Outputs().ByName("res").PipeTo(
fm.Components().ByName("case").Inputs().ByName("i1"),
)

fm.Components().ByName("concat").Outputs().ByName("res").PipeTo(
fm.Components().ByName("case").Inputs().ByName("i1"),
)
// Init inputs
fm.Components().ByName("concat").Inputs().ByName("i1").PutSignals(signal.New("hello "))
fm.Components().ByName("concat").Inputs().ByName("i2").PutSignals(signal.New("world !"))

// Init inputs
fm.Components().ByName("concat").InputByName("i1").PutSignals(signal.New("hello "))
fm.Components().ByName("concat").InputByName("i2").PutSignals(signal.New("world !"))
// Run the mesh
_, err := fm.Run()

// Run the mesh
_, err := fm.Run()
// Check for errors
if err != nil {
fmt.Println("F-Mesh returned an error")
os.Exit(1)
}

// Check for errors
if err != nil {
fmt.Println("F-Mesh returned an error")
os.Exit(1)
}

//Extract results
results := fm.Components().ByName("case").OutputByName("res").FirstSignalPayloadOrNil()
fmt.Printf("Result is : %v", results)
//Extract results
results := fm.Components().ByName("case").Outputs().ByName("res").FirstSignalPayloadOrNil()
fmt.Printf("Result is :%v", results)
```
See more in [examples](https://github.com/hovsep/fmesh/tree/main/examples) directory.
<h2>Version <a href="https://github.com/hovsep/fmesh/releases/tag/v0.0.1-alpha">0.1.0-Sugunia</a> is already released!</h2>
71 changes: 71 additions & 0 deletions component/activation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package component

import (
"errors"
"fmt"
)

type ActivationFunc func(this *Component) error

// WithActivationFunc sets activation function
func (c *Component) WithActivationFunc(f ActivationFunc) *Component {
if c.HasErr() {
return c
}

c.f = f
return c
}

// hasActivationFunction checks when activation function is set
func (c *Component) hasActivationFunction() bool {
if c.HasErr() {
return false
}

return c.f != nil
}

// MaybeActivate tries to run the activation function if all required conditions are met
func (c *Component) MaybeActivate() (activationResult *ActivationResult) {
c.propagateChainErrors()

if c.HasErr() {
activationResult = NewActivationResult(c.Name()).WithErr(c.Err())
return
}

defer func() {
if r := recover(); r != nil {
activationResult = c.newActivationResultPanicked(fmt.Errorf("panicked with: %v", r))
}
}()

if !c.hasActivationFunction() {
//Activation function is not set (maybe useful while the mesh is under development)
activationResult = c.newActivationResultNoFunction()
return
}

if !c.Inputs().AnyHasSignals() {
//No inputs set, stop here
activationResult = c.newActivationResultNoInput()
return
}

//Invoke the activation func
err := c.f(c)

if errors.Is(err, errWaitingForInputs) {
activationResult = c.newActivationResultWaitingForInputs(err)
return
}

if err != nil {
activationResult = c.newActivationResultReturnedError(err)
return
}

activationResult = c.newActivationResultOK()
return
}
Loading

0 comments on commit 0ab2e70

Please sign in to comment.