xysched

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2022 License: MIT Imports: 10 Imported by: 0

README

Xybor founder Go Reference GitHub Repo stars GitHub top language GitHub go.mod Go version GitHub release (release name instead of tag name) Codacy Badge Codacy Badge Go Report

Introduction

Package xysched supports to schedule future tasks with a simple syntax.

Features

There are two most important objects in this library:

  • Future defines tasks.
  • Scheduler manages to schedule Future instances.

Scheduler uses a channel to know when and which Future should be run. A Future could be sent to this channel via After method and its variants:

func (s *Scheduler) After(d *time.Duration) chan<-Future
func (s *Scheduler) Now() chan<-Future
func (s *Scheduler) At(t *time.Time) chan<-Future

When a Future is sent via After, it will be called by Scheduler after a duration d. This method is non-blocking.

There are some types of Future. For example, Task and Cron.

Task is a Future running only one time, wheares Cron could run periodically.

For development, Task should be the base struct of all Future structs. Task supports to add callback Futures, which is called after Task completed. It also helps to handle the returned or panicked value, which is equivalent to javascript Promise.

Cron also bases on Task, so Cron has all methods of Task.

Example

  1. Print a message after one second.
xysched.After(time.Second) <- xysched.NewTask(fmt.Println, "this is a message")
  1. Increase x, then print a message.
var x int = 0

var future = xysched.NewTask(func() { x++ })
future.Callback(fmt.Println, "increase x")

xysched.Now() <- future
  1. Print a message every second.
xysched.Now() <- xysched.NewCron(fmt.Println, "welcome").Secondly()
  1. Increase x, then print a message. Loop over seven times. After all, print x.
var x int = 0
var future = xyshed.NewCron(func(){ x++ }).Secondly().Times(7)
future.Callback(fmt.Println, "increase x")
future.Finish(fmt.Printf, "the final value of x: %d\n", x)

xysched.Now() <- future
  1. It is also possible to use Then and Catch methods to handle the returned value of Future or recover if it panicked.
func foo(b bool) string {
    if b {
        panic("foo panicked")
    } else {
        return "foo bar"
    }
}

var future = xysched.NewTask(foo, true)
future.Then(func(s string) { fmt.Println(s) })
future.Catch(func(e error) { fmt.Println(e) })

xysched.Now() <- future
  1. Create a new scheduler if it is necessary. Scheduler with non-empty name can be used in many places without a global variable.
// a.go
var scheduler = xysched.NewScheduler("foo")
defer sched.Stop()
scheduler.After(3 * time.Second) <- xysched.NewTask(fmt.Println, "x")

// b.go
var scheduler = xysched.NewScheduler("foo")

// A scheduler should be stopped if it won't be used anymore.
scheduler.Stop()
  1. Early stop a future.
var sched = xysched.NewScheduler("")
defer sched.Stop()

var captured string
var task = xysched.NewTask(func() { captured = "run" })
sched.After(time.Millisecond) <- task
task.Stop()

time.Sleep(2 * time.Millisecond)
xycond.AssertEmpty(captured)

Documentation

Overview

Package xysched supports to schedule future tasks with a simple syntax.

Example
package main

import (
	"fmt"
	"time"

	"github.com/xybor-x/xysched"
)

func main() {
	// Example 1: You can use the global scheduler throughout program without
	// creating a new one.
	var done = make(chan any)
	var future = xysched.NewTask(func() {
		fmt.Println("1. bar bar")
		close(done)
	})
	xysched.Now() <- future
	<-done

	// Example 2: Scheduler can schedule one future After or At a time.
	done = make(chan any)
	future = xysched.NewTask(func() {
		fmt.Println("2. barfoo")
		close(done)
	})
	xysched.After(time.Millisecond) <- future
	<-done

}
Output:

1. bar bar
2. barfoo

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	CallError = egen.NewClass("CallError")
)

Errors of package xysched.

Functions

func After

func After(d time.Duration) chan<- future

After creates a send-only channel. Sending a future to this channel will add it to scheduler after a duration. If d is negative, After will send the future to scheduler immediately.

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

func At

func At(next time.Time) chan<- future

At is a shortcut of After(time.Until(next)).

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

func Now

func Now() chan<- future

Now is a shortcut of After(0).

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

Types

type Cron

type Cron struct {
	// cron struct is a wrapper of task
	Task
	// contains filtered or unexported fields
}

Cron is a future which runs a task periodically.

Example
package main

import (
	"fmt"
	"time"

	"github.com/xybor-x/xysched"
)

func wait(c chan any, n int) {
	for i := 0; i < n; i++ {
		<-c
	}
}

func main() {
	var scheduler = xysched.NewScheduler("")
	// Example 1: Cron is a future which runs function periodically. By default,
	// it runs secondly forever.
	var done = make(chan any)
	var future = xysched.NewCron(func(a ...any) {
		fmt.Println(a...)
		done <- nil
	}, "1.", "foo", "bar")
	scheduler.Now() <- future
	wait(done, 2)
	scheduler.Stop()

	scheduler = xysched.NewScheduler("")
	defer scheduler.Stop()
	// Example 2: It can modify periodic duration and the maximum times the
	// function could run.
	done = make(chan any)
	future = xysched.NewCron(func() {
		fmt.Println("2. bar bar")
		done <- nil
	}).Every(time.Millisecond).Twice()
	scheduler.Now() <- future
	wait(done, 2)

	// Example 3: Callback, Then, Catch can also be used on cron.
	done = make(chan any)
	future = xysched.NewCron(fmt.Println, "3.", "foobar").Times(3)
	future.Every(time.Millisecond)
	future.Callback(func() { done <- nil })
	scheduler.Now() <- future
	wait(done, 3)

	// Example 4: Finish adds a callback future which will be run when cron ran
	// out of times.
	done = make(chan any)
	future = xysched.NewCron(fmt.Println, "4.", "foobar").Twice()
	future.Every(time.Millisecond)
	future.Finish(func() { close(done) })
	scheduler.Now() <- future
	wait(done, 1)

}
Output:

1. foo bar
1. foo bar
2. bar bar
2. bar bar
3. foobar
3. foobar
3. foobar
4. foobar
4. foobar

func NewCron

func NewCron(f any, params ...any) *Cron

NewCron creates a future which calls function f with parameter params periodically. By default, it runs the function forever secondly.

func (*Cron) Daily

func (c *Cron) Daily() *Cron

Daily requires the cron to run once per day.

func (*Cron) Every

func (c *Cron) Every(d time.Duration) *Cron

Every requires the cron to run with a custom periodic duration.

func (*Cron) Finish

func (c *Cron) Finish(f any, params ...any) *Task

Finish sets a callback future which will run after the cron ran out of times. See task.Callback for further details.

func (*Cron) Hourly

func (c *Cron) Hourly() *Cron

Hourly requires the cron to run once per hour.

func (*Cron) Minutely

func (c *Cron) Minutely() *Cron

Minutely requires the cron to run the cron once per minute.

func (*Cron) Once

func (c *Cron) Once() *Cron

Once is a shortcut of Times(1)

func (*Cron) Secondly

func (c *Cron) Secondly() *Cron

Secondly requires the cron to run once per second.

func (*Cron) Stop

func (c *Cron) Stop()

Stop early stops the Cron. If the Cron hasn't been scheduled yet, it will be never scheduled. If the Cron was scheduled, next runs will be canceled.

func (*Cron) String

func (c *Cron) String() string

String supports to print the task to output.

func (*Cron) Times

func (c *Cron) Times(n uint) *Cron

Times sets the maximum times which the cron will run.

func (*Cron) Twice

func (c *Cron) Twice() *Cron

Twice is a shortcut of Times(2)

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler is used for scheduling future objects.

func NewScheduler

func NewScheduler(name string) *Scheduler

NewScheduler returns Scheduler associated with the name, if it has not yet existed, create a new one.

Any Scheduler with a non-empty name will be associated with its name. Calling this function twice with the same name gives you the same Scheduler. If you want to create different Schedulers each call, use the empty name.

func (*Scheduler) After

func (s *Scheduler) After(d time.Duration) chan<- future

After creates a send-only channel. Sending a future to this channel will add it to scheduler after a duration. If d is negative, After will send the future to scheduler immediately.

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

func (*Scheduler) At

func (s *Scheduler) At(next time.Time) chan<- future

At is a shortcut of After(time.Until(next)).

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

func (*Scheduler) Concurrent

func (s *Scheduler) Concurrent(n int)

Concurrent limits the number of running futures at the same time. By default, there is no limited.

func (*Scheduler) Now

func (s *Scheduler) Now() chan<- future

Now is a shortcut of After(0).

NOTE: You should send ONLY ONE future to this channel because it is designed to handle one. If you try sending another, it will be blocked forever. To send other futures to scheduler, let call this method again.

func (*Scheduler) Singleton

func (s *Scheduler) Singleton()

Singleton is a shortcut of Concurrent(1).

func (*Scheduler) Stop

func (s *Scheduler) Stop()

Stop terminates the scheduler and all pending futures from now on. Running futures still run until they complete.

type Task

type Task struct {
	// contains filtered or unexported fields
}

Task is a future which runs one time.

Example
package main

import (
	"fmt"

	"github.com/xybor-x/xysched"
)

func panicFunc() {
	panic("custom panic function")
}

func main() {
	var scheduler = xysched.NewScheduler("")
	defer scheduler.Stop()

	// Example 1: Task is a simple future used for scheduling to run a function.
	var done = make(chan any)
	var future = xysched.NewTask(func(a ...any) {
		fmt.Println(a...)
		close(done)
	}, "1. foo")
	scheduler.Now() <- future
	<-done

	// Example 2: Callback will be run after the task completed.
	done = make(chan any)
	future = xysched.NewTask(fmt.Println, "2. foo foo")
	future.Callback(func() { close(done) })
	scheduler.Now() <- future
	<-done

	// Example 3: Then adds a callback handling returned values of task after
	// task completed.
	done = make(chan any)
	future = xysched.NewTask(fmt.Sprintf, "3. foo %s", "bar")
	future.Then(func(s string) {
		fmt.Println(s)
		close(done)
	})
	scheduler.Now() <- future
	<-done

	// Example 4: Catch adds a callback handling the panicked error of task if
	// the task panicked.
	// NOTE: if task panics a non-error interface, it will be wrapped into
	//       xysched.CallError.
	done = make(chan any)
	future = xysched.NewTask(panicFunc)
	future.Then(func() {
		fmt.Println("4. Then branch")
		close(done)
	})
	future.Catch(func(e error) {
		fmt.Println("4. Catch branch", e)
		close(done)
	})
	scheduler.Now() <- future
	<-done

}
Output:

1. foo
2. foo foo
3. foo bar
4. Catch branch CallError: custom panic function

func NewTask

func NewTask(f any, p ...any) *Task

NewTask creates a future which runs function f with parameters params. This future runs only one time.

func (*Task) Callback

func (t *Task) Callback(f any, params ...any) *Task

Callback sets a callback future which will run after the task completed. The parameter params only should be used if f is a function. In case f was already a future, DO NOT use.

It returns the callback task if you passed a function or task, otherwise, nil.

func (*Task) Catch

func (t *Task) Catch(f any) *Task

Catch sets a callback task which will be run after this task panicked. The only parameter of the callback task is the panicked error.

It returns the callback task.

func (*Task) Stop

func (t *Task) Stop()

Stop stops scheduling the Task if it hasn't been scheduled yet.

func (*Task) String

func (t *Task) String() string

String supports to print the task to output.

func (*Task) Then

func (t *Task) Then(f any) *Task

Then sets a callback task which will be run after this task ran successfully. The callback task's input parameters are the output of this task.

It returns the callback task.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL