Giter Site home page Giter Site logo

go-future-context's Introduction

** Capital One built this project to help our engineers as well as users in the community. We are no longer able to fully support the project. We have archived the project as of Jul 9 2019 where it will be available in a read-only state. Feel free to fork the project and maintain your own version. **

Go Report Card Sourcegraph

future

A simple Future (Promise) library for Go.

Usage

Basic usage (wait forever):

package main

import (
  "fmt"
  future "github.com/capitalone/go-future-context"
)

func ThingThatTakesALongTimeToCalculate(inVal int) (string, error) {
  //this does something but it's not that important
  return "Hello", nil
}

func main() {
  inVal := 200
  f := future.New(func() (interface{}, error) {
    return ThingThatTakesALongTimeToCalculate(inVal)
  })
  
  result, err := f.Get()
  fmt.Println(result, err)
}

Timeout usage (wait for specified amount of time):

package main

import (
	"fmt"
	future "github.com/capitalone/go-future-context"
	"time"
)

func ThingThatTakesALongTimeToCalculate(inVal int) (string, error) {
  //this does something but it's not that important
  return "Hello", nil
}

func main() {
  inVal := 200
  f := future.New(func() (interface{}, error) {
    return ThingThatTakesALongTimeToCalculate(inVal)
  })
  
  result, timeout, err := f.GetUntil(5 * time.Second)
  fmt.Println(result, timeout, err)
}

timeout will be true if the timeout was triggered.

  • The future methods Get and GetUntil can be called multiple times.
  • Once the value is calculated, the same value (and error) will be returned immediately.

Chaining usage (invoke a next method if the Promise doesn't return an error):

package main

import (
	"fmt"
	future "github.com/capitalone/go-future-context"
	"time"
)

func ThingThatTakesALongTimeToCalculate(inVal int) (int, error) {
	//this does something but it's not that important
	time.Sleep(5 * time.Second)
	return inVal * 2, nil
}

func main() {
	inVal := 200
	f := future.New(func() (interface{}, error) {
		return ThingThatTakesALongTimeToCalculate(inVal)
	}).Then(func(i interface{}) (interface{}, error) {
		return ThingThatTakesALongTimeToCalculate(i.(int))
	})

    result, err := f.Get()
    fmt.Println(result, err)
}

You can use Then to chain together as many promises as you want.

  • If an error is returned at any step along the way, the rest of the calls in the promise chain are skipped.
  • Only the value and error of the last executed promise is returned; all others are lost.

Cancellation (stop waiting for a Get or GetUntil to complete):

package main

import (
	"fmt"
	future "github.com/capitalone/go-future-context"
	"time"
)

func ThingThatTakesALongTimeToCalculate(inVal int) (int, error) {
	//this does something but it's not that important
	time.Sleep(5 * time.Second)
	return inVal * 2, nil
}

func timeIt(f func()) int64 {
	start := time.Now()
	f()
	end := time.Now()
	dur := end.Unix() - start.Unix()
	return dur
}

func main() {
	inVal := 200
	f := future.New(func() (interface{}, error) {
		return ThingThatTakesALongTimeToCalculate(inVal)
	})

	go func() {
		time.Sleep(2 * time.Second)
		f.Cancel()
	}()
	fmt.Println(timeIt(func() {
		result, err := f.Get()
		fmt.Println(result, err, f.IsCancelled())
	}))
}
  • Calling Cancel after a Get or GetUntil has completed has no effect.
  • Calling Cancel multiple times has no effect.
  • When a future is cancelled, the process continues in the background but any data returned is not accessible.
  • If GetUntil returns due to a timeout, it does not cancel the future. If you wish to cancel based on a GetUntil timeout, do the following:
	f := future.New(func() (interface{}, error) {
		return ThingThatTakesALongTimeToCalculate(inVal)
	})
    val, timeout, err := f.GetUntil(2000)
    if timeout {
        f.Cancel()
    }

Context support: Future contains support for the Context interface included in Go 1.7:

package main

import (
	"fmt"
	future "github.com/capitalone/go-future-context"
	"time"
	"context"
)

func ThingThatTakesALongTimeToCalculate(inVal int) (int, error) {
	//this does something but it's not that important
	time.Sleep(5 * time.Second)
	return inVal * 2, nil
}

func timeIt(f func()) int64 {
	start := time.Now()
	f()
	end := time.Now()
	dur := end.Unix() - start.Unix()
	return dur
}

func main() {
	inVal := 200
	ctx, _ := context.WithTimeout(context.Background(),2*time.Second)

	f := future.NewWithContext(ctx, func() (interface{}, error) {
		return ThingThatTakesALongTimeToCalculate(inVal)
	})

	fmt.Println(timeIt(func() {
		result, err := f.Get()
		fmt.Println(result, err, f.IsCancelled())
	}))
}

When a future is created using NewWithContext, it is cancelled when the Context's Done channel is closed, whether it is closed due to timeout or an explicit call to the CancelFunc returned by the Context factory functions.

Contributors:

We welcome your interest in Capital One’s Open Source Projects (the “Project”). Any Contributor to the project must accept and sign a CLA indicating agreement to the license terms. Except for the license granted in this CLA to Capital One and to recipients of software distributed by Capital One, you reserve all right, title, and interest in and to your contributions; this CLA does not impact your rights to use your own contributions for any other purpose.

Link to Individual CLA

Link to Corporate CLA

This project adheres to the Open Source Code of Conduct. By participating, you are expected to honor this code.

go-future-context's People

Contributors

brianteeman avatar jonbodner avatar santhisridharan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-future-context's Issues

future.Cancel is not safe to be called concurrently

The following program panics after a few seconds running

package main

import (
        "sync"

        future "github.com/capitalone/go-future-context"
)

func loop() {
        const N = 2000
        start := make(chan int)
        var done sync.WaitGroup
        done.Add(N)
        f := future.New(func() (interface{}, error) { select {}; return 1, nil })
        for i := 0; i < N; i++ {
                go func() {
                        defer done.Done()
                        <-start
                        f.Cancel()
                }()
        }
        close(start)
        done.Wait()
}

func main() {
        for {
                loop()
        }
}

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.