Beispiel #1
0
func TestRepeatingDelayOK(tst *testing.T) {

	decoupler := NewDecoupler(10, nil, nil)

	go decoupler.ProcessLoop(1 * time.Second)

	l := latch.NewCountdownLatch(5)
	latchShort := latch.NewCountdownLatch(1)

	task := func() (executor.ExecutionResult, error) {
		l.CountDown()
		if !latchShort.Completed() {
			latchShort.CountDown()
		}
		return executor.EX_OK, nil
	}

	decoupler.ExecuteEvery(1*time.Second, 1*time.Second, 5, task)

	// We want this latch to time out.
	if !latchShort.AwaitTimeout(1 * time.Second) {
		tst.Fatal("Should fail.")
	}

	// This one should not time out.
	if l.AwaitTimeout(12 * time.Second) {
		tst.Fatal("Task did not complete", l.Canceled(), l.TimedOut())
	}

	decoupler.StopProcessLoop(1 * time.Second)

}
Beispiel #2
0
func TestErrorCalled(tst *testing.T) {

	decoupler := NewDecoupler(10, nil, nil)

	go decoupler.ProcessLoop(1 * time.Second)

	l := latch.NewCountdownLatch(1)
	errorLatch := latch.NewCountdownLatch(1)

	decoupler.SetOnError(func(*Decoupler, *executor.TaskCell) executor.ExecutionResult {
		errorLatch.CountDown()
		return executor.EX_DROP
	})

	task := func() (executor.ExecutionResult, error) {
		l.CountDown()
		return executor.EX_FAILED, errors.New("Aardvark application error")
	}

	decoupler.ExecuteEvery(1*time.Second, 1*time.Second, 5, task)

	// We want this latch to time out.
	if errorLatch.AwaitTimeout(5 * time.Second) {
		tst.Fatal("Error latch failed to fire.")
	}

	// This one should not time out.
	if l.AwaitTimeout(5 * time.Second) {
		tst.Fatal("Task did not complete", l.Canceled(), l.TimedOut())
	}

	decoupler.StopProcessLoop(1 * time.Second)
}
Beispiel #3
0
func TestDropCalled(tst *testing.T) {

	decoupler := NewDecoupler(1, nil, nil)

	go decoupler.ProcessLoop(1 * time.Second)

	dropLatch := latch.NewCountdownLatch(2)

	decoupler.SetOnDrop(func(*Decoupler, *executor.TaskCell) {
		dropLatch.CountDown()
	})

	task := func() (executor.ExecutionResult, error) {
		time.Sleep(2 * time.Second)
		return executor.EX_OK, nil
	}

	time.AfterFunc(2*time.Second, func() {
		decoupler.Execute(task) // This may get picked up immediately.
		decoupler.Execute(task) // So we need three to ensure while the first is blocking
		decoupler.Execute(task) // The remainder attempt to overflow.
	})

	// We want this latch to time out.
	if dropLatch.AwaitTimeout(5 * time.Second) {
		tst.Fatal("Error latch failed to fire.")
	}

	decoupler.StopProcessLoop(1 * time.Second)
}
Beispiel #4
0
func (c *CatServiceProviderLocal) AddCat(name string, legs int) {
	l := latch.NewCountdownLatch(1)
	acr := addCatRequest{name, legs, l, c}
	c.dec.Execute(acr.Run)

	l.Await() // Use the timeout version if you wish..
}
Beispiel #5
0
//
// Set a value on the map.
//
func (r *Register) AddEntry(name string) {

	ltch := latch.NewCountdownLatch(1)

	task := registerAddTask{r, ltch, name}
	r.dec.Execute(task.Run)

	ltch.Await()
}
Beispiel #6
0
func TestNormalExecute(tst *testing.T) {

	decoupler := NewDecoupler(10, nil, nil)

	go decoupler.ProcessLoop(1 * time.Second)

	l := latch.NewCountdownLatch(1)

	task := func() (executor.ExecutionResult, error) {
		l.CountDown()
		return executor.EX_OK, nil
	}

	decoupler.ExecuteAfter(2*time.Second, task)

	// This one should not time out.
	if l.AwaitTimeout(3 * time.Second) {
		tst.Fatal("Task did not complete", l.Canceled(), l.TimedOut())
	}

	decoupler.StopProcessLoop(1 * time.Second)

}
Beispiel #7
0
// NewFutureWithListener with an optional listener.
//
func NewFutureWithListener(onValue func(bool, interface{})) *Future {
	return &Future{latch.NewCountdownLatch(1), nil, 0, &sync.Mutex{}, &sync.Mutex{}, onValue}
}
Beispiel #8
0
// NewFuture creates a new future with no listener.
//
func NewFuture() *Future {
	return &Future{latch.NewCountdownLatch(1), nil, 0, &sync.Mutex{}, &sync.Mutex{}, nil}
}
Beispiel #9
0
func main() {

	sites := []string{"http://www.theage.com.au", "http://www.cisco.com", "http://www.dilbert.com", "www.google.com"}

	results := make([]*QueryResult, len(sites))

	l := latch.NewCountdownLatch(len(sites))

	// A function that fetches the content of a web page and sets a pointer to the content into a result array.
	search := func(resultIndex int, query string) {

		//
		// Note the order of declaration of each defer statement.
		//
		defer func() {
			// If the await has completed(finished an await) then an attempt to count down will fail.
			// We can catch this and squash it for the sake of the example.
			r := recover()
			if r != nil {
				if lerr, ok := r.(latch.LatchError); ok {
					println(query, lerr.Error())
				}
			}
		}()

		//
		// Attempt a latch countdown.
		//
		defer l.CountDown()

		resp, err := http.Get(query)
		if err != nil {
			results[resultIndex] = &QueryResult{Error: err}
			return
		}

		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)

		if err != nil {
			results[resultIndex] = &QueryResult{Error: err}
			return
		}
		results[resultIndex] = &QueryResult{query, nil, body}
	}

	//
	// Spin up a new go routine for each query.
	//
	for t, v := range sites {
		go search(t, v)
	}

	//
	// Wait 2 seconds for the requests to complete..
	//
	if l.AwaitTimeout(2 * time.Second) {
		// An issue occurred.
		if l.Canceled() {
			// It was canceled.
		}

		if l.TimedOut() {
			println("Distributed query timed out..")
		}
	}

	//
	// Print the results.
	//
	for t, v := range results {

		if v == nil {
			println("Query ", t, "Did not return in time.")
			continue
		}

		println(t, "Query: ", v.Query)
		if v.Error != nil {
			println("  Error:", v.Error.Error())
		} else {
			println("  Body Length: ", len(v.Body))
		}
	}

}