Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Commit

Permalink
Merge branch 'fix-log-messages' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
hut8 committed May 1, 2022
2 parents cb33203 + 0850464 commit 35b577a
Show file tree
Hide file tree
Showing 6 changed files with 319 additions and 39 deletions.
16 changes: 15 additions & 1 deletion default_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
var _ Context = &DefaultContext{}
var _ context.Context = &DefaultContext{}

// TODO(sio4): #road-to-v1 - make DefaultContext private
// and only allow it to be generated by App.newContext() or any similar.

// DefaultContext is, as its name implies, a default
// implementation of the Context interface.
type DefaultContext struct {
Expand Down Expand Up @@ -67,16 +70,22 @@ func (d *DefaultContext) Param(key string) string {
// Set a value onto the Context. Any value set onto the Context
// will be automatically available in templates.
func (d *DefaultContext) Set(key string, value interface{}) {
if d.data == nil {
d.data = &sync.Map{}
}
d.data.Store(key, value)
}

// Value that has previously stored on the context.
func (d *DefaultContext) Value(key interface{}) interface{} {
if k, ok := key.(string); ok {
if k, ok := key.(string); ok && d.data != nil {
if v, ok := d.data.Load(k); ok {
return v
}
}
if d.Context == nil {
return nil
}
return d.Context.Value(key)
}

Expand Down Expand Up @@ -235,6 +244,11 @@ func (d *DefaultContext) Redirect(status int, url string, args ...interface{}) e
// Data contains all the values set through Get/Set.
func (d *DefaultContext) Data() map[string]interface{} {
m := map[string]interface{}{}

if d.data == nil {
return m
}

d.data.Range(func(k, v interface{}) bool {
s, ok := k.(string)
if !ok {
Expand Down
81 changes: 80 additions & 1 deletion default_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ func Test_DefaultContext_GetSet(t *testing.T) {
r.Equal("Mark", c.Value("name").(string))
}

func Test_DefaultContext_Set_Unconfigured(t *testing.T) {
r := require.New(t)
c := DefaultContext{}

c.Set("name", "Yonghwan")
r.NotNil(c.Value("name"))
r.Equal("Yonghwan", c.Value("name").(string))
}

func Test_DefaultContext_Value(t *testing.T) {
r := require.New(t)
c := basicContext()
Expand All @@ -151,7 +160,12 @@ func Test_DefaultContext_Value(t *testing.T) {
c.Set("name", "Mark")
r.NotNil(c.Value("name"))
r.Equal("Mark", c.Value("name").(string))
r.Equal("Mark", c.Value("name").(string))
}

func Test_DefaultContext_Value_Unconfigured(t *testing.T) {
r := require.New(t)
c := DefaultContext{}
r.Nil(c.Value("name"))
}

func Test_DefaultContext_Render(t *testing.T) {
Expand Down Expand Up @@ -301,3 +315,68 @@ func Test_DefaultContext_Bind_JSON(t *testing.T) {

r.Equal("Mark", user.FirstName)
}

func Test_DefaultContext_Data(t *testing.T) {
r := require.New(t)
c := basicContext()

r.EqualValues(map[string]interface{}{}, c.Data())
}

func Test_DefaultContext_Data_Unconfigured(t *testing.T) {
r := require.New(t)
c := DefaultContext{}

r.EqualValues(map[string]interface{}{}, c.Data())
}

func Test_DefaultContext_String(t *testing.T) {
r := require.New(t)
c := basicContext()
c.Set("name", "Buffalo")
c.Set("language", "go")

r.EqualValues("language: go\n\nname: Buffalo", c.String())
}

func Test_DefaultContext_String_EmptyData(t *testing.T) {
r := require.New(t)
c := basicContext()
r.EqualValues("", c.String())
}

func Test_DefaultContext_String_EmptyData_Unconfigured(t *testing.T) {
r := require.New(t)
c := DefaultContext{}

r.EqualValues("", c.String())
}

func Test_DefaultContext_MarshalJSON(t *testing.T) {
r := require.New(t)
c := basicContext()
c.Set("name", "Buffalo")
c.Set("language", "go")

jb, err := c.MarshalJSON()
r.NoError(err)
r.EqualValues(`{"language":"go","name":"Buffalo"}`, string(jb))
}

func Test_DefaultContext_MarshalJSON_EmptyData(t *testing.T) {
r := require.New(t)
c := basicContext()

jb, err := c.MarshalJSON()
r.NoError(err)
r.EqualValues(`{}`, string(jb))
}

func Test_DefaultContext_MarshalJSON_EmptyData_Unconfigured(t *testing.T) {
r := require.New(t)
c := DefaultContext{}

jb, err := c.MarshalJSON()
r.NoError(err)
r.EqualValues(`{}`, string(jb))
}
4 changes: 2 additions & 2 deletions plugins/plugins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package plugins

import (
"context"
"io/ioutil"
"os"
"strings"
"testing"
"time"
Expand All @@ -20,7 +20,7 @@ func TestAskBin_respectsTimeout(t *testing.T) {
return
}

if fileEntries, err := ioutil.ReadDir(from); err == nil {
if fileEntries, err := os.ReadDir(from); err == nil {
found := false
for _, e := range fileEntries {
if strings.HasPrefix(e.Name(), "buffalo-") {
Expand Down
18 changes: 9 additions & 9 deletions router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package buffalo

import (
"fmt"
"io/ioutil"
"io"
"net/http"
"os"
"path"
Expand Down Expand Up @@ -98,7 +98,7 @@ func Test_Mount_Buffalo(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, _ := ioutil.ReadAll(res.Body)
b, _ := io.ReadAll(res.Body)
r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b))
}
}
Expand All @@ -123,7 +123,7 @@ func Test_Mount_Buffalo_on_Group(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, _ := ioutil.ReadAll(res.Body)
b, _ := io.ReadAll(res.Body)
r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b))
}
}
Expand Down Expand Up @@ -158,7 +158,7 @@ func Test_Mount_Handler(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, _ := ioutil.ReadAll(res.Body)
b, _ := io.ReadAll(res.Body)
r.Equal(fmt.Sprintf("%s - %s/", m, u), string(b))
}
}
Expand Down Expand Up @@ -197,7 +197,7 @@ func Test_PreHandlers(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, err := ioutil.ReadAll(res.Body)
b, err := io.ReadAll(res.Body)
r.NoError(err)
r.Equal(v.Code, res.StatusCode)
r.Equal(v.Result, string(b))
Expand Down Expand Up @@ -242,7 +242,7 @@ func Test_PreWares(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, err := ioutil.ReadAll(res.Body)
b, err := io.ReadAll(res.Body)
r.NoError(err)
r.Equal(v.Code, res.StatusCode)
r.Equal(v.Result, string(b))
Expand All @@ -269,7 +269,7 @@ func Test_Router(t *testing.T) {
r.NoError(err)
res, err := http.DefaultClient.Do(req)
r.NoError(err)
b, _ := ioutil.ReadAll(res.Body)
b, _ := io.ReadAll(res.Body)
r.Equal(fmt.Sprintf("%s|/router/tests", v), string(b))
}
}
Expand Down Expand Up @@ -552,7 +552,7 @@ func Test_Resource(t *testing.T) {
r.NoError(err)
res, err := c.Do(req)
r.NoError(err)
b, err := ioutil.ReadAll(res.Body)
b, err := io.ReadAll(res.Body)
r.NoError(err)
r.Equal(test.Result, string(b))
}
Expand Down Expand Up @@ -710,7 +710,7 @@ func Test_ResourceOnResource(t *testing.T) {
r.NoError(err)
res, err := c.Do(req)
r.NoError(err)
b, err := ioutil.ReadAll(res.Body)
b, err := io.ReadAll(res.Body)
r.NoError(err)
r.Equal(test.Result, string(b))
}
Expand Down
33 changes: 30 additions & 3 deletions worker/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ var _ Worker = &Simple{}
// NewSimple creates a basic implementation of the Worker interface
// that is backed using just the standard library and goroutines.
func NewSimple() *Simple {
// TODO(sio4): #road-to-v1 - how to check if the worker is ready to work
// when worker should be initialized? how to check if worker is ready?
// and purpose of the context
return NewSimpleWithContext(context.Background())
}

Expand Down Expand Up @@ -49,6 +52,10 @@ type Simple struct {

// Register Handler with the worker
func (w *Simple) Register(name string, h Handler) error {
if name == "" || h == nil {
return fmt.Errorf("name or handler cannot be empty/nil")
}

w.moot.Lock()
defer w.moot.Unlock()
if _, ok := w.handlers[name]; ok {
Expand All @@ -60,6 +67,7 @@ func (w *Simple) Register(name string, h Handler) error {

// Start the worker
func (w *Simple) Start(ctx context.Context) error {
// TODO(sio4): #road-to-v1 - define the purpose of Start clearly
w.Logger.Info("starting Simple background worker")

w.ctx, w.cancel = context.WithCancel(ctx)
Expand All @@ -68,28 +76,38 @@ func (w *Simple) Start(ctx context.Context) error {

// Stop the worker
func (w *Simple) Stop() error {
// prevent job submission when stopping
w.moot.Lock()
defer w.moot.Unlock()

w.Logger.Info("stopping Simple background worker")

w.cancel()

w.wg.Wait()
w.Logger.Info("all background jobs stopped completely")
w.cancel()
return nil
}

// Perform a job as soon as possibly using a goroutine.
func (w *Simple) Perform(job Job) error {
// Perform should not allow a job submission if the worker is not running
if err := w.ctx.Err(); err != nil {
return fmt.Errorf("worker is not ready to perform a job: %v", err)
}

w.Logger.Debugf("performing job %s", job)

if job.Handler == "" {
err := fmt.Errorf("no handler name given for %s", job)
err := fmt.Errorf("no handler name given: %s", job)
w.Logger.Error(err)
return err
}

w.moot.Lock()
defer w.moot.Unlock()
if h, ok := w.handlers[job.Handler]; ok {
// TODO: consider to implement timeout and/or cancellation
// TODO(sio4): #road-to-v1 - consider timeout and/or cancellation
w.wg.Add(1)
go func() {
defer w.wg.Done()
Expand Down Expand Up @@ -118,11 +136,20 @@ func (w *Simple) PerformAt(job Job, t time.Time) error {
// PerformIn performs a job after waiting for a specified amount
// using a goroutine.
func (w *Simple) PerformIn(job Job, d time.Duration) error {
// Perform should not allow a job submission if the worker is not running
if err := w.ctx.Err(); err != nil {
return fmt.Errorf("worker is not ready to perform a job: %v", err)
}

w.wg.Add(1) // waiting job also should be counted
go func() {
defer w.wg.Done()

select {
case <-time.After(d):
w.Perform(job)
case <-w.ctx.Done():
// TODO(sio4): #road-to-v1 - it should be guaranteed to be performed
w.cancel()
}
}()
Expand Down
Loading

0 comments on commit 35b577a

Please sign in to comment.