Skip to content

Commit

Permalink
Merge pull request #31 from donutloop/feat/lease
Browse files Browse the repository at this point in the history
Leaser: Lease the resource for duration. When the lease expires, invo…
  • Loading branch information
donutloop committed Dec 22, 2017
2 parents 1b892e2 + ec96059 commit 6711adb
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 2 deletions.
4 changes: 2 additions & 2 deletions debugutil/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Usage

PrettyPrint generates a human readable representation of the value v.
PrettySprint generates a human readable representation of the value v.

## Example
```go
Expand All @@ -12,6 +12,6 @@ import (
)

func main() {
debugutil.PrettyPrint([]string{})
log.Println(debugutil.PrettySprint([]string{})
}
```
19 changes: 19 additions & 0 deletions lease/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Usage

lease the resource for duration. When the lease expires, invoke func

## Example
```go
package main

import (
"github.com/donutloop/toolkit/lease"
)

func main() {
leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
fmt.Println("cleaned up cache")
})
}
```
20 changes: 20 additions & 0 deletions lease/doc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package lease_test

import (
"fmt"
"time"

"github.com/donutloop/toolkit/lease"
)

func ExampleLeaser_Lease() {

leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
fmt.Println("cleaned up cache")
})

<-time.After(2 * time.Second)

// Output: cleaned up cache
}
40 changes: 40 additions & 0 deletions lease/lease.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lease

import "time"

type Leaser interface {
// lease the resource r for duration. When the lease expires, invoke func call.
// revoke a lease can be refreshed by calling Lease() again on the same resource
Lease(r string, d time.Duration, revoke func())
// if resource exists then cancel the old timer and delete the entry
Return(r string) bool
}

// NewLeaser creates a instance of leaser
func NewLeaser() Leaser {
return &leaser{
timers: make(map[string]*time.Timer),
}
}

type leaser struct {
timers map[string]*time.Timer
}

func (l *leaser) Lease(r string, d time.Duration, f func()) {
timer := time.AfterFunc(d, f)
// if resource exists then cancel the old timer and overwrite the old one
if t, ok := l.timers[r]; ok {
t.Stop()
}
l.timers[r] = timer
}

// if resource exists then cancel the old timer and delete the entry
func (l *leaser) Return(r string) bool {
if t, ok := l.timers[r]; ok {
t.Stop()
return true
}
return false
}
61 changes: 61 additions & 0 deletions lease/lease_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package lease_test

import (
"testing"
"time"

"sync/atomic"

"github.com/donutloop/toolkit/lease"
)

func TestLeaser_Lease(t *testing.T) {
var counter int32
leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
atomic.AddInt32(&counter, 1)
})

<-time.After(2 * time.Second)

if counter != 1 {
t.Errorf(`unexpected counter value (actual:"%d", expected: "%d")`, counter, 1)
}
}

func TestLeaser_OverwriteLease(t *testing.T) {
var counter int32
leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(2*time.Second), func() {
atomic.AddInt32(&counter, 1)
})

leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
atomic.AddInt32(&counter, 2)
})

<-time.After(3 * time.Second)

if counter != 2 {
t.Errorf(`unexpected counter value (actual:"%d", expected: "%d")`, counter, 2)
}
}

func TestLeaser_Return(t *testing.T) {
var counter int32
leaser := lease.NewLeaser()
leaser.Lease("cleanup-cache", time.Duration(1*time.Second), func() {
atomic.AddInt32(&counter, 1)
})

ok := leaser.Return("cleanup-cache")
if !ok {
t.Error("error couldn't return resource")
}

<-time.After(2 * time.Second)

if counter != 0 {
t.Errorf(`unexpected counter value (actual:"%d", expected: "%d")`, counter, 0)
}
}

0 comments on commit 6711adb

Please sign in to comment.