github.com/ngicks/gokugen@v0.0.5/example/persistent_shceduler/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math/rand"
     8  	"os"
     9  	"path/filepath"
    10  	"time"
    11  
    12  	"github.com/ngicks/gokugen"
    13  	"github.com/ngicks/gokugen/impl/repository"
    14  	workregistry "github.com/ngicks/gokugen/impl/work_registry"
    15  	"github.com/ngicks/gokugen/scheduler"
    16  	taskstorage "github.com/ngicks/gokugen/task_storage"
    17  	syncparam "github.com/ngicks/type-param-common/sync-param"
    18  )
    19  
    20  func main() {
    21  	if err := _main(); err != nil {
    22  		panic(err)
    23  	}
    24  }
    25  
    26  func printJsonIndent(j any) {
    27  	b, err := json.MarshalIndent(j, "", "    ")
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	fmt.Println(string(b))
    32  }
    33  
    34  type Param1 struct {
    35  	Foo string
    36  	Bar string
    37  }
    38  
    39  func (p Param1) Mix() string {
    40  	var ret string
    41  	for range p.Foo {
    42  		for range p.Bar {
    43  			ret += string(p.Foo[rand.Int63n(int64(len(p.Foo)))])
    44  			ret += string(p.Bar[rand.Int63n(int64(len(p.Bar)))])
    45  		}
    46  	}
    47  	return ret
    48  }
    49  
    50  type Param2 struct {
    51  	Baz string
    52  	Qux string
    53  }
    54  
    55  func (p Param2) Double() string {
    56  	var runes []rune
    57  	for _, bRune := range p.Baz {
    58  		for _, qRune := range p.Qux {
    59  			runes = append(runes, bRune)
    60  			runes = append(runes, qRune)
    61  		}
    62  	}
    63  	return string(runes)
    64  }
    65  
    66  func printNowWithIdParam1(workId string) gokugen.WorkFnWParam {
    67  	return func(taskCtx context.Context, scheduled time.Time, param any) (any, error) {
    68  		printer(workId, taskCtx, scheduled, param.(Param1).Mix())
    69  		return nil, nil
    70  	}
    71  }
    72  
    73  func printNowWithIdParam2(workId string) gokugen.WorkFnWParam {
    74  	return func(taskCtx context.Context, scheduled time.Time, param any) (any, error) {
    75  		printer(workId, taskCtx, scheduled, param.(Param2).Double())
    76  		return nil, nil
    77  	}
    78  }
    79  
    80  func printer(workId string, taskCtx context.Context, scheduled time.Time, param string) {
    81  	now := time.Now()
    82  	var isCtxCancelled bool
    83  	select {
    84  	case <-taskCtx.Done():
    85  		isCtxCancelled = true
    86  	default:
    87  	}
    88  
    89  	fmt.Printf(
    90  		"workId: %s, scheduled: %s, diff to now: %s, isCtxCancelled: %t, param: %s\n",
    91  		workId,
    92  		scheduled.Format(time.RFC3339Nano),
    93  		now.Sub(scheduled).String(),
    94  		isCtxCancelled,
    95  		param,
    96  	)
    97  }
    98  
    99  func prepare(dbFilename string) (
   100  	sched *gokugen.MiddlewareApplicator[*scheduler.Scheduler],
   101  	repo *repository.Sqlite3Repo,
   102  	workRegistory taskstorage.WorkRegistry,
   103  	taskStorage *taskstorage.SingleNodeTaskStorage,
   104  	err error,
   105  ) {
   106  	repo, err = repository.NewSql3Repo(dbFilename)
   107  	if err != nil {
   108  		return
   109  	}
   110  	innerRegistry := &syncparam.Map[string, gokugen.WorkFnWParam]{}
   111  	innerRegistry.Store("func1", printNowWithIdParam1("func1"))
   112  	innerRegistry.Store("func2", printNowWithIdParam2("func2"))
   113  	innerRegistry.Store("func3", printNowWithIdParam2("func3"))
   114  
   115  	unmarshallerResgitry := &workregistry.AnyUnmarshaller{}
   116  	workregistry.AddType[Param1]("func1", unmarshallerResgitry)
   117  	workregistry.AddType[Param2]("func2", unmarshallerResgitry)
   118  	workregistry.AddType[Param2]("func3", unmarshallerResgitry)
   119  
   120  	workRegistory = workregistry.NewParamUnmarshaller(innerRegistry, unmarshallerResgitry)
   121  
   122  	sched = gokugen.NewMiddlewareApplicator(scheduler.NewScheduler(5, 0))
   123  
   124  	taskStorage = taskstorage.NewSingleNodeTaskStorage(
   125  		repo,
   126  		func(ti taskstorage.TaskInfo) bool { return true },
   127  		workRegistory,
   128  		nil,
   129  	)
   130  	sched.Use(taskStorage.Middleware(true)...)
   131  
   132  	return
   133  }
   134  
   135  func _main() (err error) {
   136  	p, err := os.MkdirTemp("", "sqlite3-tmp-*")
   137  	if err != nil {
   138  		return
   139  	}
   140  	dbFilename := filepath.Join(p, "db")
   141  
   142  	sched, repo, _, _, err := prepare(dbFilename)
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	now := time.Now()
   148  
   149  	sched.Schedule(
   150  		gokugen.BuildContext(
   151  			now,
   152  			nil,
   153  			nil,
   154  			gokugen.WithWorkId("func1"),
   155  			gokugen.WithParam(Param1{Foo: "param", Bar: "qqq"}),
   156  		),
   157  	)
   158  	sched.Schedule(
   159  		gokugen.BuildContext(
   160  			now.Add(1*time.Second),
   161  			nil,
   162  			nil,
   163  			gokugen.WithWorkId("func2"),
   164  			gokugen.WithParam(Param2{Baz: "baaz", Qux: "param"}),
   165  		),
   166  	)
   167  	sched.Schedule(
   168  		gokugen.BuildContext(
   169  			now.Add(3*time.Second),
   170  			nil,
   171  			nil,
   172  			gokugen.WithWorkId("func3"),
   173  			gokugen.WithParam(Param2{Baz: "quuux", Qux: "coorrge"}),
   174  		),
   175  	)
   176  
   177  	ctx, cancel := context.WithDeadline(context.Background(), now.Add(2*time.Second))
   178  	sched.Scheduler().Start(ctx)
   179  	cancel()
   180  	sched.Scheduler().End()
   181  
   182  	fmt.Println("after 1st teardown: tasks in repository")
   183  	taskInfos, err := repo.GetAll()
   184  	if err != nil {
   185  		return
   186  	}
   187  	for _, v := range taskInfos {
   188  		printJsonIndent(v)
   189  	}
   190  
   191  	sched, _, _, taskStorage, err := prepare(dbFilename)
   192  	if err != nil {
   193  		return
   194  	}
   195  
   196  	rescheduled, schedulingErr, err := taskStorage.Sync(sched.Schedule)
   197  	if err != nil {
   198  		return
   199  	}
   200  	fmt.Println("restoed from persistent data storage:")
   201  	printJsonIndent(rescheduled)
   202  	printJsonIndent(schedulingErr)
   203  	for k, v := range rescheduled {
   204  		fmt.Println(k, v.GetScheduledTime())
   205  	}
   206  
   207  	ctx, cancel = context.WithDeadline(context.Background(), now.Add(5*time.Second))
   208  	sched.Scheduler().Start(ctx)
   209  	cancel()
   210  	sched.Scheduler().End()
   211  
   212  	fmt.Println("after 2nd teardown: tasks in repository")
   213  	taskInfos, err = repo.GetAll()
   214  	if err != nil {
   215  		return
   216  	}
   217  	for _, v := range taskInfos {
   218  		printJsonIndent(v)
   219  	}
   220  
   221  	return
   222  }