Skip to content

Commit

Permalink
Merge pull request #3 from phr3nzy/refactor/release
Browse files Browse the repository at this point in the history
Refactor/release
  • Loading branch information
phr3nzy authored May 29, 2024
2 parents c8e7941 + 19077b3 commit cc09249
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 116 deletions.
24 changes: 24 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# MIT License

Copyright (c) 2024 Osama Adil

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Package: github.com/phr3nzy/tango
Contact: <[email protected]>
67 changes: 67 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Description: Makefile for the project

# Variables
BINARY_NAME=tango
VERSION=0.1.0
BUILD=`date +%FT%T%z`

# Build for all platforms
build-all: build-linux build-windows build-macos

# Build the project
build:
@echo "Building the project"
@go build -o "$(BINARY_NAME)" -ldflags "-X main.Version=$(VERSION) -X main.Build=$(BUILD)" ./...

# Build for Linux optimized
build-linux:
@echo "Building the project for Linux"
@GOOS=linux GOARCH=amd64 go build -o "$(BINARY_NAME)-linux" -ldflags "-X main.Version=$(VERSION) -X main.Build=$(BUILD)" ./...

# Build for Windows optimized
build-windows:
@echo "Building the project for Windows"
@GOOS=windows GOARCH=amd64 go build -o "$(BINARY_NAME)-windows".exe -ldflags "-X main.Version=$(VERSION) -X main.Build=$(BUILD)" ./...

# Build for MacOS optimized
build-macos:
@echo "Building the project for MacOS"
@GOOS=darwin GOARCH=amd64 go build -o "$(BINARY_NAME)-macos" -ldflags "-X main.Version=$(VERSION) -X main.Build=$(BUILD)" ./...

# Run the project
run:
@echo "Running the project"
@go run main.go

# Clean the project
clean:
@echo "Cleaning the project"
@go clean
@rm -f $(BINARY_NAME)

# Test the project
test:
@echo "Running tests"
@go test ./...

# Test the project with coverage
test-coverage:
@echo "Running coverage tests"
@go test -cover ./...

# Test the project with coverage and generate HTML report
test-html-coverage:
@echo "Running coverage tests"
@go test -coverprofile=coverage.out ./...
@go tool cover -html=coverage.out
@rm coverage.out

# Benchmark the project
benchmark:
@echo "Running benchmarks"
@go test -bench ./...

# Benchmark the project with memory profiling
benchmark-mem:
@echo "Running memory benchmarks"
@go test -bench . -benchmem
101 changes: 63 additions & 38 deletions machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,40 @@ import (
"sync"
)

type MachineContext[S, T any] struct {
Services S
PreviousResult *StepResponse[S, T]
State T
Machine *Machine[S, T]
// ResponseStatus is a type that represents the status of a response.
type MachineContext[Services, State any] struct {
Services Services
PreviousResult *Response[Services, State]
State State
Machine *Machine[Services, State]
}

type MachineConfig[S, T any] struct {
// Plugin is an interface that represents a machine plugin.
type MachineConfig[Services, State any] struct {
Log bool
LogLevel string
Plugins []Plugin[S, T]
Plugins []Plugin[Services, State]
}

type Machine[S, T any] struct {
// Machine is a struct that represents a machine.
type Machine[Services, State any] struct {
Name string
Context *MachineContext[S, T]
Steps []Step[S, T]
ExecutedSteps []Step[S, T]
InitialContext *MachineContext[S, T]
Config *MachineConfig[S, T]
Context *MachineContext[Services, State]
Steps []Step[Services, State]
ExecutedSteps []Step[Services, State]
InitialContext *MachineContext[Services, State]
Config *MachineConfig[Services, State]
mu sync.Mutex
}

func NewMachine[S, T any](
// NewMachine creates a new machine.
func NewMachine[Services, State any](
name string,
steps []Step[S, T],
initialContext *MachineContext[S, T],
config *MachineConfig[S, T],
) *Machine[S, T] {
m := &Machine[S, T]{
steps []Step[Services, State],
initialContext *MachineContext[Services, State],
config *MachineConfig[Services, State],
) *Machine[Services, State] {
m := &Machine[Services, State]{
Name: name,
Steps: steps,
InitialContext: initialContext,
Expand All @@ -45,17 +49,20 @@ func NewMachine[S, T any](
return m
}

func (m *Machine[S, T]) AddStep(step Step[S, T]) {
// AddStep adds a step to the machine.
func (m *Machine[Services, State]) AddStep(step Step[Services, State]) {
m.Steps = append(m.Steps, step)
}

func (m *Machine[S, T]) Reset() {
// Reset resets the machine to its initial state. It clears the context and executed steps.
func (m *Machine[Services, State]) Reset() {
m.Steps = nil
m.Context = m.InitialContext
m.ExecutedSteps = nil
}

func (m *Machine[S, T]) Run() (*StepResponse[S, T], error) {
// Run executes the machine steps.
func (m *Machine[Services, State]) Run() (*Response[Services, State], error) {
if len(m.Steps) == 0 {
return nil, fmt.Errorf("no steps to execute")
}
Expand All @@ -79,7 +86,11 @@ func (m *Machine[S, T]) Run() (*StepResponse[S, T], error) {
case DONE:
return response, nil
case ERROR:
return nil, fmt.Errorf("execution error at %s", step.Name)
cResponse, err := m.Compensate()
if err != nil {
return nil, fmt.Errorf("compensate error: %v", err)
}
return cResponse, fmt.Errorf("step %s failed: %v", step.Name, response.Result)
case SKIP:
i += response.SkipCount
case JUMP:
Expand Down Expand Up @@ -107,12 +118,18 @@ func (m *Machine[S, T]) Run() (*StepResponse[S, T], error) {
return nil, nil
}

func (m *Machine[S, T]) executeStep(step Step[S, T]) (*StepResponse[S, T], error) {

// executeStep runs the step and its before and after functions.
func (m *Machine[Services, State]) executeStep(step Step[Services, State]) (*Response[Services, State], error) {
if m.Config.Log {
fmt.Printf("Executing step: %s\n", step.Name)
}

for _, plugin := range m.Config.Plugins {
if err := plugin.Execute(m.Context); err != nil {
return nil, fmt.Errorf("plugin before step error: %v", err)
}
}

if step.BeforeExecute != nil {
if err := step.BeforeExecute(m.Context); err != nil {
return nil, err
Expand All @@ -137,7 +154,8 @@ func (m *Machine[S, T]) executeStep(step Step[S, T]) (*StepResponse[S, T], error
return response, nil
}

func (m *Machine[S, T]) Compensate() (*StepResponse[S, T], error) {
// Compensate runs the compensate functions of the executed steps.
func (m *Machine[Services, State]) Compensate() (*Response[Services, State], error) {
m.Context = m.InitialContext
for i := len(m.ExecutedSteps) - 1; i >= 0; i-- {
step := m.ExecutedSteps[i]
Expand All @@ -161,28 +179,35 @@ func (m *Machine[S, T]) Compensate() (*StepResponse[S, T], error) {
return nil, nil
}

// Result is an alias for any.
type Result interface{}

func (m *Machine[S, T]) NewStep(step *Step[S, T]) *Step[S, T] {
return NewStep(step)
// NewStep creates a new step.
func (m *Machine[Services, State]) NewStep(step *Step[Services, State]) {
m.AddStep(*NewStep(step))
}

func (m *Machine[S, T]) Next(result Result) *StepResponse[S, T] {
return Next[Result, S, T](result)
// Next creates a response with status NEXT.
func (m *Machine[Services, State]) Next(result Result) *Response[Services, State] {
return Next[Result, Services, State](result)
}

func (m *Machine[S, T]) Done(result Result) *StepResponse[S, T] {
return Done[Result, S, T](result)
// Done creates a response with status DONE.
func (m *Machine[Services, State]) Done(result Result) *Response[Services, State] {
return Done[Result, Services, State](result)
}

func (m *Machine[S, T]) Error(result Result) *StepResponse[S, T] {
return Error[Result, S, T](result)
// Error creates a response with status ERROR.
func (m *Machine[Services, State]) Error(result Result) *Response[Services, State] {
return Error[Result, Services, State](result)
}

func (m *Machine[S, T]) Skip(result Result, count int) *StepResponse[S, T] {
return Skip[Result, S, T](result, count)
// Skip creates a response with status SKIP.
func (m *Machine[Services, State]) Skip(result Result, count int) *Response[Services, State] {
return Skip[Result, Services, State](result, count)
}

func (m *Machine[S, T]) Jump(result any, target string) *StepResponse[S, T] {
return Jump[Result, S, T](result, target)
// Jump creates a response with status JUMP.
func (m *Machine[Services, State]) Jump(result any, target string) *Response[Services, State] {
return Jump[Result, Services, State](result, target)
}
Loading

0 comments on commit cc09249

Please sign in to comment.