interactor

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2023 License: MIT Imports: 4 Imported by: 0

README

Interactor

Build Status codecov

Interactor is a simple and efficient Go package for managing and dispatching requests to the appropriate use cases according to their request types. It is inspired by Uncle Bob's Clean Architecture and the interactor concept described therein.

The library is designed to be well-documented, thoroughly tested, and easy to use, ensuring maintainable and reliable code for your projects.

Features

  • Dispatcher for managing different use cases.
  • Flexible use cases as either pure functions or structures.
  • Well-documented and tested code.

Installation

To install the Interactor Library, run the following command:

go get -u github.com/screwyprof/interactor

Usage

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/screwyprof/interactor"
)

// TestRequest represents a test request.
type TestRequest struct{}

// TestResponse represents a test response.
type TestResponse struct {
	Result int
}

// UseCase is an example use case implementation.
type UseCase struct {
	Res int
}

// Run runs the use case with the given request.
//
// The response is returned by reference to avoid extra allocations.
func (uc UseCase) Run(ctx context.Context, req TestRequest, res *TestResponse) error {
	res.Result = uc.Res
	return nil
}

func main() {
	// Create a use case.
	useCaseRunner := &UseCase{Res: 42}

	// Create a new dispatcher and register the use case runner.
	dispatcher := interactor.NewDispatcher()
	dispatcher.Register(TestRequest{}, interactor.MustAdapt(useCaseRunner.Run))

	// Run the use case
	var res TestResponse
	if err := dispatcher.Run(context.Background(), TestRequest{}, &res); err != nil {
		log.Fatal(err)
	}

	fmt.Printf("The answer to life, the universe, and everything: %d\n", res.Result)
}

Documentation

For more information and detailed documentation, please refer to the GoDoc documentation:

Interactor Library GoDoc

Contributing

Contributions are welcome! If you have any suggestions, bug reports, or feature requests, please open a new issue or submit a pull request.

License

The Interactor Library is released under the MIT License.

Documentation

Overview

Package interactor provides a flexible library for running use cases.

This package allows registering use cases for different request types, efficiently dispatching requests to the appropriate handlers.

Example usage:

func ExampleDispatcher() {
	// arrange
	useCaseRunner := &ConcreteUseCase{res: 42}

	dispatcher := interactor.NewDispatcher()
	dispatcher.Register(TestRequest{}, interactor.MustAdapt(useCaseRunner.RunUseCase))

	// act
	var res TestResponse
	if err := dispatcher.Run(context.Background(), TestRequest{}, &res); err != nil {
		log.Fatal(err)
	}

	fmt.Printf("The answer to life the universe and everything: %d\n", res.result)

	// Output:
	// The answer to life the universe and everything: 42
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidUseCaseRunnerSignature = errors.New("useCaseRunner must have 3 input params")
	ErrUseCaseRunnerIsNotAFunction   = errors.New("useCaseRunner is not a function")
	ErrFirstArgHasInvalidType        = errors.New("first input argument must have context.Context type")
	ErrSecondArgHasInvalidType       = errors.New("second input argument must implement Request interface")
	ErrThirdArgHasInvalidType        = errors.New("third input argument must implement Response interface")
	ErrResultTypeMismatch            = errors.New("result type mismatch")
)

Guard errors.

View Source
var ErrUseCaseRunnerNotFound = errors.New("use case runner not registered for the given request type")

ErrUseCaseRunnerNotFound is returned when the use case runner is not registered for the given Request type.

Functions

This section is empty.

Types

type Dispatcher

type Dispatcher struct {
	// contains filtered or unexported fields
}

Dispatcher manages registered UseCaseRunners and dispatches requests to the appropriate UseCaseRunner.

Example
// arrange
useCaseRunner := &ConcreteUseCase{}

dispatcher := interactor.NewDispatcher()
dispatcher.Register(TestRequest{}, interactor.MustAdapt(useCaseRunner.RunUseCase))

// act
var res TestResponse
if err := dispatcher.Run(context.Background(), TestRequest{id: 42}, &res); err != nil {
	log.Fatal(err)
}

fmt.Printf("The answer to life the universe and everything: %d\n", res.result)
Output:

The answer to life the universe and everything: 42

func NewDispatcher

func NewDispatcher() *Dispatcher

NewDispatcher creates a new Dispatcher instance.

func (*Dispatcher) Register

func (d *Dispatcher) Register(request Request, runner UseCaseRunnerFn)

Register registers the given UseCaseRunner for the provided request type.

func (*Dispatcher) Run

func (d *Dispatcher) Run(ctx context.Context, req Request, resp Response) error

Run runs a use case with the given Request and writes the result to the provided Response.

It returns nil if the use case was executed successfully. It returns ErrUseCaseRunnerNotFound if the use case runner is not registered for the Request type.

type Request

type Request interface{}

Request is an interface representing the input for the use case.

type Response

type Response interface{}

Response is an interface representing the output from the use case.

type UseCaseRunner

type UseCaseRunner interface {
	// Run executes the given request and writes the result to the provided response.
	Run(ctx context.Context, req Request, resp Response) error
}

UseCaseRunner is an interface that defines a contract for running a use case.

type UseCaseRunnerFn

type UseCaseRunnerFn func(ctx context.Context, req Request, resp Response) error

UseCaseRunnerFn allows using pure functions as a UseCaseRunner.

func Adapt

func Adapt(fn interface{}) (UseCaseRunnerFn, error)

Adapt is a helper function that converts a function with the appropriate signature into a UseCaseRunnerFn.

The function must have the following signature:

  1. Have 3 arguments: * ctx context.Context, * req a struct which implements Request interface, * res a pointer to a struct which implements Response interface.
  2. Return an error

An example signature may look like as follows:

func(ctx context.Context, req TestRequest, res *TestResponse) error

func MustAdapt

func MustAdapt(fn interface{}) UseCaseRunnerFn

MustAdapt is a wrapper around Adapt which panics if an error occurs.

It is useful for tests and for cases where you are sure that the signature is valid.

func (UseCaseRunnerFn) Run

func (fn UseCaseRunnerFn) Run(ctx context.Context, req Request, resp Response) error

Run executes the given request and writes the result to the provided response.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL