Git Product home page Git Product logo

routines's Introduction

Go Reference Go Report Card Build Status codecov License: MIT

Routines

Golang package for enhanced goroutine synchronization and well defined idiomatic Golang services.

Dependencies

  • github.com/nofeaturesonlybugs/errors

Write Idiomatic Client Code

bus and listen are considered mock packages for this example.

func fatal(e err) {
    if e != nil {
        fmt.Println("Error", e)
        os.Exit(255)
    }
}

func main() {
    // Top-level Routines object.
    rtns := routines.NewRoutines()
    // WaitGroup-like behavior providing clean shutdown.
    defer rtns.Wait()

    bus := bus.NewBus()
    err := bus.Start(rtns)
    fatal(err)
    defer bus.Stop()

    listener, err := listen.New("localhost:8080")
    fatal(err)
    err = listener.Start(rtns)
    fatal(err)
    defer listener.Stop()

    // Program stalls waiting on sigc or other shutdown signal...
}

The preceding example demonstrates the following well-defined behaviors:

  • Calls to Start() block until the service is fully started, preventing race conditions
    • Returns an error if the service can not start
  • Calls to Stop() block until the service is fully stopped, preventing race conditions

Write Lean Services

The Service interface provides the well-defined behavior of Start and Stop without polluting your service implementation.

type MyService struct {
    Routines.Service
}

func NewMyService() *MyService {
    rv := &MyService{}
    rv.Service = routines.NewService(rv.start)
    return rv
}

func (me *MyService) start(rtns routines.Routines) error {
    listener, err := net.Listen("localhost:8080")
    if err != nil {
        return err
    }
    closed := make(chan struct{}, 1)

    // Create a lambda function that handls the connection; we'll pass the
    // returned function to rtns.Go() to ensure all handlers are finished
    // when the service stops.
    handler := func(c net.Conn) func() {
        return func() {
            io.Copy(c, c)
            c.Close()
        }
    }
    // Continuous loop that accepts and handles connections.
    accept := func() {
        for {
            if conn, err := listener.Accept(); err != nil {
                select {
                    case <-closed:
                        goto done
                    default:
                        // Handle error
                }
            } else {
                rtns.Go(handler(conn))
            }
        }
        done:
    }
    // When rtns.Done() signals we close the listener; this ends the accept
    // function.
    cleanup := func() {
        <- rtns.Done()
        close(closed)
        listener.Close()
    }
    rtns.Go(cleanup)
    rtns.Go(accept)
    return nil
}

The preceding example is not concerned with the concurrency primitives required to implement correct Start and Stop behavior; it is only concerned with correctly implementing the service behavior.

All goroutines created by the service are invoked with rtns.Go(). This ensures clean shutdown when the client calls Stop() as Stop() will not return until all such goroutines have completed.

Also notice that the struct itself is not storing any variables or resources created as part of starting the service. Such resources are instantiated in the call to start() and then remembered by the goroutines of the service. When the service is stopped all of these goroutines will end; the handles to the resources will disappear and they will be garbage collected. There is no need to remember to set such struct members to nil.

routines's People

Contributors

nofeaturesonlybugs avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.