Skip to content

Commit

Permalink
refactor!: module package structure (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
reugn authored Jan 5, 2024
1 parent 49ce1d9 commit 5b8e094
Show file tree
Hide file tree
Showing 33 changed files with 487 additions and 443 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ The argument must implement the `logger.Logger` interface.
The following example shows how to disable library logs.

```go
import "github.com/reugn/go-quartz/quartz/logger"
import "github.com/reugn/go-quartz/logger"

logger.SetDefault(logger.NewSimpleLogger(nil, logger.LevelOff))
```
Expand All @@ -133,6 +133,7 @@ import (
"net/http"
"time"

"github.com/reugn/go-quartz/job"
"github.com/reugn/go-quartz/quartz"
)

Expand All @@ -148,12 +149,12 @@ func main() {

// create jobs
cronTrigger, _ := quartz.NewCronTrigger("1/5 * * * * *")
shellJob := quartz.NewShellJob("ls -la")
shellJob := job.NewShellJob("ls -la")

request, _ := http.NewRequest(http.MethodGet, "https://worldtimeapi.org/api/timezone/utc", nil)
curlJob := quartz.NewCurlJob(request)
curlJob := job.NewCurlJob(request)

functionJob := quartz.NewFunctionJob(func(_ context.Context) (int, error) { return 42, nil })
functionJob := job.NewFunctionJob(func(_ context.Context) (int, error) { return 42, nil })

// register jobs to scheduler
sched.ScheduleJob(quartz.NewJobDetail(shellJob, quartz.NewJobKey("shellJob")),
Expand Down
7 changes: 4 additions & 3 deletions examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"syscall"
"time"

"github.com/reugn/go-quartz/job"
"github.com/reugn/go-quartz/quartz"
)

Expand Down Expand Up @@ -84,14 +85,14 @@ func sampleJobs(ctx context.Context, wg *sync.WaitGroup) {
return
}

shellJob := quartz.NewShellJob("ls -la")
shellJob := job.NewShellJob("ls -la")
request, err := http.NewRequest(http.MethodGet, "https://worldtimeapi.org/api/timezone/utc", nil)
if err != nil {
fmt.Println(err)
return
}
curlJob := quartz.NewCurlJob(request)
functionJob := quartz.NewFunctionJobWithDesc("42", func(_ context.Context) (int, error) { return 42, nil })
curlJob := job.NewCurlJob(request)
functionJob := job.NewFunctionJobWithDesc("42", func(_ context.Context) (int, error) { return 42, nil })

shellJobDetail := quartz.NewJobDetail(shellJob, quartz.NewJobKey("shellJob"))
curlJobDetail := quartz.NewJobDetail(curlJob, quartz.NewJobKey("curlJob"))
Expand Down
7 changes: 4 additions & 3 deletions examples/readme/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"time"

"github.com/reugn/go-quartz/job"
"github.com/reugn/go-quartz/quartz"
)

Expand All @@ -20,12 +21,12 @@ func main() {

// create jobs
cronTrigger, _ := quartz.NewCronTrigger("1/5 * * * * *")
shellJob := quartz.NewShellJob("ls -la")
shellJob := job.NewShellJob("ls -la")

request, _ := http.NewRequest(http.MethodGet, "https://worldtimeapi.org/api/timezone/utc", nil)
curlJob := quartz.NewCurlJob(request)
curlJob := job.NewCurlJob(request)

functionJob := quartz.NewFunctionJob(func(_ context.Context) (int, error) { return 42, nil })
functionJob := job.NewFunctionJob(func(_ context.Context) (int, error) { return 42, nil })

// register jobs to scheduler
sched.ScheduleJob(quartz.NewJobDetail(shellJob, quartz.NewJobKey("shellJob")),
Expand Down
18 changes: 18 additions & 0 deletions internal/assert/assert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package assert

import (
"reflect"
"testing"
)

func Equal[T any](t *testing.T, a T, b T) {
if !reflect.DeepEqual(a, b) {
t.Fatalf("%v != %v", a, b)
}
}

func NotEqual[T any](t *testing.T, a T, b T) {
if reflect.DeepEqual(a, b) {
t.Fatalf("%v == %v", a, b)
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
40 changes: 40 additions & 0 deletions internal/mock/http_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package mock

import (
"net/http"

"github.com/reugn/go-quartz/job"
)

type HTTPHandlerMock struct {
DoFunc func(req *http.Request) (*http.Response, error)
}

func (m HTTPHandlerMock) Do(req *http.Request) (*http.Response, error) {
return m.DoFunc(req)
}

var (
HTTPHandlerOk job.HTTPHandler
HTTPHandlerErr job.HTTPHandler
)

func init() {
HTTPHandlerMockOk := struct{ HTTPHandlerMock }{}
HTTPHandlerMockOk.DoFunc = func(request *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Request: request,
}, nil
}
HTTPHandlerOk = job.HTTPHandler(HTTPHandlerMockOk)

HTTPHandlerMockErr := struct{ HTTPHandlerMock }{}
HTTPHandlerMockErr.DoFunc = func(request *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 500,
Request: request,
}, nil
}
HTTPHandlerErr = job.HTTPHandler(HTTPHandlerMockErr)
}
115 changes: 115 additions & 0 deletions job/curl_job.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package job

import (
"context"
"fmt"
"net/http"
"net/http/httputil"
"strings"
"sync"

"github.com/reugn/go-quartz/quartz"
)

// CurlJob represents a cURL command Job, implements the quartz.Job interface.
// cURL is a command-line tool for getting or sending data including files
// using URL syntax.
type CurlJob struct {
sync.Mutex
httpClient HTTPHandler
request *http.Request
response *http.Response
jobStatus Status
description string
callback func(context.Context, *CurlJob)
}

var _ quartz.Job = (*CurlJob)(nil)

// HTTPHandler sends an HTTP request and returns an HTTP response,
// following policy (such as redirects, cookies, auth) as configured
// on the implementing HTTP client.
type HTTPHandler interface {
Do(req *http.Request) (*http.Response, error)
}

// CurlJobOptions represents optional parameters for constructing a CurlJob.
type CurlJobOptions struct {
HTTPClient HTTPHandler
Callback func(context.Context, *CurlJob)
}

// NewCurlJob returns a new CurlJob using the default HTTP client.
func NewCurlJob(request *http.Request) *CurlJob {
return NewCurlJobWithOptions(request, CurlJobOptions{HTTPClient: http.DefaultClient})
}

// NewCurlJobWithOptions returns a new CurlJob configured with CurlJobOptions.
func NewCurlJobWithOptions(request *http.Request, opts CurlJobOptions) *CurlJob {
if opts.HTTPClient == nil {
opts.HTTPClient = http.DefaultClient
}
return &CurlJob{
httpClient: opts.HTTPClient,
request: request,
jobStatus: StatusNA,
description: formatRequest(request),
callback: opts.Callback,
}
}

// Description returns the description of the CurlJob.
func (cu *CurlJob) Description() string {
return fmt.Sprintf("CurlJob:\n%s", cu.description)
}

// DumpResponse returns the response of the job in its HTTP/1.x wire
// representation.
// If body is true, DumpResponse also returns the body.
func (cu *CurlJob) DumpResponse(body bool) ([]byte, error) {
cu.Lock()
defer cu.Unlock()
return httputil.DumpResponse(cu.response, body)
}

// JobStatus returns the status of the CurlJob.
func (cu *CurlJob) JobStatus() Status {
cu.Lock()
defer cu.Unlock()
return cu.jobStatus
}

func formatRequest(r *http.Request) string {
var request []string
url := fmt.Sprintf("%v %v %v", r.Method, r.URL, r.Proto)
request = append(request, url)
for name, headers := range r.Header {
for _, h := range headers {
request = append(request, fmt.Sprintf("%v: %v", name, h))
}
}
if r.ContentLength > 0 {
request = append(request, fmt.Sprintf("Content Length: %d", r.ContentLength))
}
return strings.Join(request, "\n")
}

// Execute is called by a Scheduler when the Trigger associated with this job fires.
func (cu *CurlJob) Execute(ctx context.Context) error {
cu.Lock()
cu.request = cu.request.WithContext(ctx)
var err error
cu.response, err = cu.httpClient.Do(cu.request)

if err == nil && cu.response.StatusCode >= 200 && cu.response.StatusCode < 400 {
cu.jobStatus = StatusOK
} else {
cu.jobStatus = StatusFailure
}
cu.Unlock()

if cu.callback != nil {
cu.callback(ctx, cu)
}
return nil
}
2 changes: 2 additions & 0 deletions job/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package job contains implementations of the quartz.Job interface.
package job
18 changes: 10 additions & 8 deletions quartz/function_job.go → job/function_job.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package quartz
package job

import (
"context"
"fmt"
"sync"

"github.com/reugn/go-quartz/quartz"
)

// Function represents an argument-less function which returns
Expand All @@ -18,17 +20,17 @@ type FunctionJob[R any] struct {
desc string
result *R
err error
jobStatus JobStatus
jobStatus Status
}

var _ Job = (*FunctionJob[any])(nil)
var _ quartz.Job = (*FunctionJob[any])(nil)

// NewFunctionJob returns a new FunctionJob without an explicit description.
func NewFunctionJob[R any](function Function[R]) *FunctionJob[R] {
return &FunctionJob[R]{
function: &function,
desc: fmt.Sprintf("FunctionJob:%p", &function),
jobStatus: NA,
jobStatus: StatusNA,
}
}

Expand All @@ -37,7 +39,7 @@ func NewFunctionJobWithDesc[R any](desc string, function Function[R]) *FunctionJ
return &FunctionJob[R]{
function: &function,
desc: desc,
jobStatus: NA,
jobStatus: StatusNA,
}
}

Expand All @@ -52,11 +54,11 @@ func (f *FunctionJob[R]) Execute(ctx context.Context) error {
result, err := (*f.function)(ctx)
f.Lock()
if err != nil {
f.jobStatus = FAILURE
f.jobStatus = StatusFailure
f.result = nil
f.err = err
} else {
f.jobStatus = OK
f.jobStatus = StatusOK
f.result = &result
f.err = nil
}
Expand All @@ -79,7 +81,7 @@ func (f *FunctionJob[R]) Error() error {
}

// JobStatus returns the status of the FunctionJob.
func (f *FunctionJob[R]) JobStatus() JobStatus {
func (f *FunctionJob[R]) JobStatus() Status {
f.RLock()
defer f.RUnlock()
return f.jobStatus
Expand Down
Loading

0 comments on commit 5b8e094

Please sign in to comment.