Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
language: go
sudo: false
go:
- 1.4.2
- 1.5.1
- 1.6
- tip
matrix:
allow_failures:
- go: tip
script:
- go vet ./...
- go test -v ./...

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["queue_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["queue.go"],
importpath = "go-common/app/admin/main/up/util/timerqueue",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_xtest",
srcs = ["example_test.go"],
tags = ["automanaged"],
deps = ["//app/admin/main/up/util/timerqueue:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,91 @@
[![Build Status](https://travis-ci.org/beevik/timerqueue.svg?branch=master)](https://travis-ci.org/beevik/timerqueue)
[![GoDoc](https://godoc.org/github.com/beevik/timerqueue?status.svg)](https://godoc.org/github.com/beevik/timerqueue)
timerqueue
==========
The timerqueue package implements a priority queue for objects scheduled to
perform actions at clock times.
See http://godoc.org/github.com/beevik/timerqueue for godoc-formatted API
documentation.
###Example: Scheduling timers
The following code declares an object implementing the Timer interface,
creates a timerqueue, and adds three events to the timerqueue.
```go
type event int
func (e event) OnTimer(t time.Time) {
fmt.Printf("event.OnTimer %d fired at %v\n", int(e), t)
}
queue := timerqueue.New()
queue.Schedule(event(1), time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC))
queue.Schedule(event(2), time.Date(2015, 1, 3, 0, 0, 0, 0, time.UTC))
queue.Schedule(event(3), time.Date(2015, 1, 2, 0, 0, 0, 0, time.UTC))
```
###Example: Peeking at the next timer to be scheduled
Using the queue initialized in the first example, the following code
examines the head of the timerqueue and outputs the id and time of
the event found there.
```go
e, t := queue.PeekFirst()
if e != nil {
fmt.Printf("Event %d will be first to fire at %v.\n", int(e.(event)), t)
fmt.Printf("%d events remain in the timerqueue.", queue.Len())
}
```
Output:
```
Event 1 will be first to fire at 2015-01-01 00:00:00 +0000 UTC.
3 events remain in the timerqueue.
```
###Example: Popping the next timer to be scheduled
Using the queue initialized in the first example, this code
removes the next timer to be executed until the queue is empty.
```go
for queue.Len() > 0 {
e, t := queue.PopFirst()
fmt.Printf("Event %d fires at %v.\n", int(e.(event)), t)
}
```
Output:
```
Event 1 fires at 2015-01-01 00:00:00 +0000 UTC.
Event 3 fires at 2015-01-02 00:00:00 +0000 UTC.
Event 2 fires at 2015-01-03 00:00:00 +0000 UTC.
```
###Example: Issuing OnTimer callbacks with Advance
The final example shows how to dispatch OnTimer callbacks to
timers using the timerqueue's Advance method.
Advance calls the OnTimer method for each timer scheduled
before the requested time. Timers are removed from the timerqueue
in order of their scheduling.
```go
// Call the OnTimer method for each event scheduled before
// January 10, 2015. Pop the called timer from the queue.
queue.Advance(time.Date(2015, 1, 10, 0, 0, 0, 0, time.UTC))
```
Output:
```
event.OnTimer 1 fired at 2015-01-01 00:00:00 +0000 UTC.
event.OnTimer 3 fired at 2015-01-02 00:00:00 +0000 UTC.
event.OnTimer 2 fired at 2015-01-03 00:00:00 +0000 UTC.
```

View File

@@ -0,0 +1,44 @@
package timerqueue_test
import (
"fmt"
"time"
"go-common/app/admin/main/up/util/timerqueue"
)
type event int
func (e event) OnTimer(t time.Time) {
fmt.Printf(" Event %d executed at %v\n", int(e), t)
}
// Schedule several events with a timerqueue, and dispatch
// them by calling Advance.
func ExampleQueue() {
queue := timerqueue.New()
// Schedule an event each day from Jan 1 to Jan 7, 2015.
tm := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)
for i := 1; i <= 7; i++ {
queue.Schedule(event(i), tm)
tm = tm.Add(24 * time.Hour)
}
fmt.Println("Advancing to Jan 4...")
queue.Advance(time.Date(2015, 1, 4, 0, 0, 0, 0, time.UTC))
fmt.Println("Advancing to Jan 10...")
queue.Advance(time.Date(2015, 1, 10, 0, 0, 0, 0, time.UTC))
// Output:
// Advancing to Jan 4...
// Event 1 executed at 2015-01-01 00:00:00 +0000 UTC
// Event 2 executed at 2015-01-02 00:00:00 +0000 UTC
// Event 3 executed at 2015-01-03 00:00:00 +0000 UTC
// Event 4 executed at 2015-01-04 00:00:00 +0000 UTC
// Advancing to Jan 10...
// Event 5 executed at 2015-01-05 00:00:00 +0000 UTC
// Event 6 executed at 2015-01-06 00:00:00 +0000 UTC
// Event 7 executed at 2015-01-07 00:00:00 +0000 UTC
}

View File

@@ -0,0 +1,181 @@
// Package timerqueue implements a priority queue for objects scheduled at a
// particular time.
package timerqueue
import (
"container/heap"
"errors"
"time"
)
// Timer is an interface that types implement to schedule and receive OnTimer
// callbacks.
type Timer interface {
OnTimer(t time.Time)
}
//NewTimerWrapper util struct
func NewTimerWrapper(fun TimerFunc) (result *TimerWrapper) {
result = &TimerWrapper{fun}
return
}
//TimerFunc timer function
type TimerFunc func(t time.Time)
//TimerWrapper just a time wrapper
type TimerWrapper struct {
fun TimerFunc
}
//OnTimer ontimer
func (t *TimerWrapper) OnTimer(tm time.Time) {
t.fun(tm)
}
// Queue is a time-sorted collection of Timer objects.
type Queue struct {
heap timerHeap
table map[Timer]*timerData
}
type timerData struct {
timer Timer
time time.Time
index int
period time.Duration // if > 0, this will be a periodically event
}
// New creates a new timer priority queue.
func New() *Queue {
return &Queue{
table: make(map[Timer]*timerData),
}
}
// Len returns the current number of timer objects in the queue.
func (q *Queue) Len() int {
return len(q.heap)
}
// Schedule schedules a timer for exectuion at time tm. If the
// timer was already scheduled, it is rescheduled.
func (q *Queue) Schedule(t Timer, tm time.Time) {
q.ScheduleRepeat(t, tm, 0)
}
// ScheduleRepeat give 0 duration, will not be repeatedly event
func (q *Queue) ScheduleRepeat(t Timer, tm time.Time, period time.Duration) {
if data, ok := q.table[t]; !ok {
data = &timerData{t, tm, 0, period}
heap.Push(&q.heap, data)
q.table[t] = data
} else {
data.time = tm
heap.Fix(&q.heap, data.index)
}
}
// Unschedule unschedules a timer's execution.
func (q *Queue) Unschedule(t Timer) {
if data, ok := q.table[t]; ok {
heap.Remove(&q.heap, data.index)
delete(q.table, t)
}
}
// GetTime returns the time at which the timer is scheduled.
// If the timer isn't currently scheduled, an error is returned.
func (q *Queue) GetTime(t Timer) (tm time.Time, err error) {
if data, ok := q.table[t]; ok {
return data.time, nil
}
return time.Time{}, errors.New("timerqueue: timer not scheduled")
}
// IsScheduled returns true if the timer is currently scheduled.
func (q *Queue) IsScheduled(t Timer) bool {
_, ok := q.table[t]
return ok
}
// Clear unschedules all currently scheduled timers.
func (q *Queue) Clear() {
q.heap, q.table = nil, make(map[Timer]*timerData)
}
// PopFirst removes and returns the next timer to be scheduled and
// the time at which it is scheduled to run.
func (q *Queue) PopFirst() (t Timer, tm time.Time) {
if len(q.heap) > 0 {
data := heap.Pop(&q.heap).(*timerData)
delete(q.table, data.timer)
return data.timer, data.time
}
return nil, time.Time{}
}
// PeekFirst returns the next timer to be scheduled and the time
// at which it is scheduled to run. It does not modify the contents
// of the timer queue.
func (q *Queue) PeekFirst() (t Timer, tm time.Time) {
if len(q.heap) > 0 {
return q.heap[0].timer, q.heap[0].time
}
return nil, time.Time{}
}
// Advance executes OnTimer callbacks for all timers scheduled to be
// run before the time 'tm'. Executed timers are removed from the
// timer queue.
func (q *Queue) Advance(tm time.Time) {
for len(q.heap) > 0 && !tm.Before(q.heap[0].time) {
data := q.heap[0]
heap.Remove(&q.heap, data.index)
if data.period > 0 {
data.time = data.time.Add(data.period)
heap.Push(&q.heap, data)
} else {
delete(q.table, data.timer)
}
data.timer.OnTimer(data.time)
}
}
/*
* timerHeap
*/
type timerHeap []*timerData
//Len len interface
func (h timerHeap) Len() int {
return len(h)
}
//Less less interface
func (h timerHeap) Less(i, j int) bool {
return h[i].time.Before(h[j].time)
}
//Swap swap interface
func (h timerHeap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
h[i].index, h[j].index = i, j
}
//Push push interface
func (h *timerHeap) Push(x interface{}) {
data := x.(*timerData)
*h = append(*h, data)
data.index = len(*h) - 1
}
//Pop pop interface
func (h *timerHeap) Pop() interface{} {
n := len(*h)
data := (*h)[n-1]
*h = (*h)[:n-1]
data.index = -1
return data
}

View File

@@ -0,0 +1,75 @@
package timerqueue
import (
"math/rand"
"testing"
"time"
)
type object struct {
value int
}
var executed int
func (o *object) OnTimer(t time.Time) {
executed++
}
func populateQueue(t *testing.T, now time.Time) *Queue {
q := New()
count := 200
objects := make([]*object, count)
// Add a bunch of objects to the queue in random order.
for i, j := range rand.Perm(count) {
tm := now.Add(time.Duration(i+1) * time.Hour)
objects[j] = &object{j}
q.Schedule(objects[j], tm)
}
if q.Len() != count {
t.Error("invalid queue length:", q.Len())
}
return q
}
func TestQueue(t *testing.T) {
for iter := 0; iter < 100; iter++ {
now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)
queue := populateQueue(t, now)
// Make sure objects are removed from the queue in order.
for prev := now; queue.Len() > 0; {
_, tm := queue.PopFirst()
if tm.Sub(prev) != time.Hour {
t.Errorf("Invalid queue ordering.\n"+
" Got: %v\n"+
"Expected: %v\n", tm, prev.Add(time.Hour))
}
prev = tm
}
}
}
func TestAdvance(t *testing.T) {
for iter := 0; iter < 100; iter++ {
now := time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)
queue := populateQueue(t, now)
executed = 0
count := queue.Len()
lastTime := now.Add(time.Duration(count) * time.Hour)
for adv := 0; adv < 5; adv++ {
queue.Advance(lastTime)
if executed != count {
t.Errorf("Advance failed.\n"+
"Should have executed %d times.\n"+
"Only executed %d times.\n", count, executed)
}
}
}
}