Skip to content

Commit d580d8e

Browse files
committed
Refactor Deferred
1 parent 18007da commit d580d8e

File tree

6 files changed

+116
-69
lines changed

6 files changed

+116
-69
lines changed

grade/internal/infrastructure/seedwork/batch/multi_query.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@ func (q MultiQuery) Evaluate(s session.DbSession) (session.Result, error) {
8484
return nil, err
8585
}
8686
for i := range q.results {
87-
err = q.results[i].Resolve(0, 0)
88-
if err != nil {
89-
errs = multierror.Append(errs, err)
87+
d := q.results[i]
88+
d.Resolve(0, 0)
89+
occurredErr := d.OccurredErr()
90+
if occurredErr != nil {
91+
errs = multierror.Append(errs, occurredErr)
9092
}
9193
}
9294
return r, errs
@@ -110,9 +112,11 @@ func (q AutoincrementMultiInsertQuery) Evaluate(s session.DbSession) (session.Re
110112
if err != nil {
111113
return nil, err
112114
}
113-
err = q.results[i].Resolve(id, 0)
114-
if err != nil {
115-
errs = multierror.Append(errs, err)
115+
d := q.results[i]
116+
d.Resolve(id, 0)
117+
occurredErr := d.OccurredErr()
118+
if occurredErr != nil {
119+
errs = multierror.Append(errs, occurredErr)
116120
}
117121
i++
118122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package deferred
2+
3+
import "github.com/hashicorp/go-multierror"
4+
5+
/**
6+
* Simplified version of
7+
* - https://github.com/emacsway/store/blob/devel/polyfill.js#L199
8+
* - https://github.com/emacsway/go-promise
9+
**/
10+
11+
func Noop[T interface{}](_ T) error { return nil }
12+
13+
type handler[T interface{}] struct {
14+
onSuccess DeferredCallback[T]
15+
onError DeferredCallback[error]
16+
next *DeferredImp[any]
17+
}
18+
19+
type DeferredImp[T interface{}] struct {
20+
value T
21+
err error
22+
occurredErr error
23+
isResolved bool
24+
isRejected bool
25+
handlers []handler[T]
26+
}
27+
28+
func (d *DeferredImp[T]) Resolve(value T) {
29+
d.value = value
30+
d.isResolved = true
31+
for _, h := range d.handlers {
32+
d.resolveHandler(h)
33+
}
34+
}
35+
36+
func (d *DeferredImp[T]) Reject(err error) {
37+
d.isRejected = true
38+
for _, h := range d.handlers {
39+
d.rejectHandler(h)
40+
}
41+
}
42+
43+
func (d *DeferredImp[T]) Then(onSuccess DeferredCallback[T], onError DeferredCallback[error]) Deferred[any] {
44+
next := &DeferredImp[any]{}
45+
h := handler[T]{
46+
onSuccess: onSuccess,
47+
onError: onError,
48+
next: next,
49+
}
50+
d.handlers = append(d.handlers, h)
51+
if d.isResolved {
52+
d.resolveHandler(h)
53+
} else if d.isRejected {
54+
d.rejectHandler(h)
55+
}
56+
return next
57+
}
58+
59+
func (d *DeferredImp[T]) resolveHandler(h handler[T]) {
60+
err := h.onSuccess(d.value)
61+
if err == nil {
62+
h.next.Resolve(true)
63+
} else {
64+
d.occurredErr = multierror.Append(d.occurredErr, err)
65+
h.next.Reject(err)
66+
}
67+
}
68+
69+
func (d *DeferredImp[T]) rejectHandler(h handler[T]) {
70+
err := h.onError(d.err)
71+
if err != nil {
72+
d.occurredErr = multierror.Append(d.occurredErr, err)
73+
h.next.Reject(err)
74+
}
75+
}
76+
77+
func (d *DeferredImp[T]) OccurredErr() error {
78+
err := d.occurredErr
79+
for _, h := range d.handlers {
80+
nestedErr := h.next.OccurredErr()
81+
if nestedErr != nil {
82+
err = multierror.Append(err, nestedErr)
83+
}
84+
}
85+
return err
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package deferred
2+
3+
type DeferredCallback[T interface{}] func(T) error
4+
5+
type Deferred[T interface{}] interface {
6+
Then(DeferredCallback[T], DeferredCallback[error]) Deferred[any]
7+
}

grade/internal/infrastructure/seedwork/session/deferred.go

-45
This file was deleted.

grade/internal/infrastructure/seedwork/session/interfaces.go

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package session
22

3-
import "github.com/emacsway/grade/grade/internal/application/seedwork/session"
3+
import (
4+
"github.com/emacsway/grade/grade/internal/application/seedwork/session"
5+
"github.com/emacsway/grade/grade/internal/infrastructure/seedwork/deferred"
6+
)
47

58
type Result interface {
69
LastInsertId() (int64, error)
@@ -51,23 +54,16 @@ type EventSourcedQueryEvaluator interface {
5154

5255
// Deferred
5356

54-
type DeferredCallback[T interface{}] func(T) error
55-
56-
type Deferred[T interface{}] interface {
57-
Then(DeferredCallback[T]) error
58-
Catch(DeferredCallback[error]) error
59-
}
60-
6157
type DeferredResult interface {
62-
Deferred[Result]
58+
deferred.Deferred[Result]
6359
}
6460

6561
type DeferredRows interface {
66-
Then(DeferredCallback[Rows]) error
62+
deferred.Deferred[Rows]
6763
}
6864

6965
type DeferredRow interface {
70-
Then(DeferredCallback[Row]) error
66+
deferred.Deferred[Row]
7167
}
7268

7369
type DeferredDbSessionExecutor interface {

grade/internal/infrastructure/seedwork/session/result.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ package session
22

33
import (
44
"errors"
5+
6+
"github.com/emacsway/grade/grade/internal/infrastructure/seedwork/deferred"
57
)
68

79
func NewResult(lastInsertId, rowsAffected int64) *DeferredResultImp {
810
r := &DeferredResultImp{}
9-
err := r.Resolve(lastInsertId, rowsAffected)
10-
if err != nil {
11-
panic(err)
12-
}
11+
r.Resolve(lastInsertId, rowsAffected)
1312
return r
1413
}
1514

@@ -39,11 +38,11 @@ func (r ResultImp) RowsAffected() (int64, error) {
3938
}
4039

4140
type DeferredResultImp struct {
42-
DeferredImp[Result]
4341
ResultImp
42+
deferred.DeferredImp[Result]
4443
}
4544

46-
func (r *DeferredResultImp) Resolve(lastInsertId, rowsAffected int64) error {
45+
func (r *DeferredResultImp) Resolve(lastInsertId, rowsAffected int64) {
4746
r.ResultImp = ResultImp{lastInsertId, rowsAffected}
48-
return r.DeferredImp.Resolve(r)
47+
r.DeferredImp.Resolve(r)
4948
}

0 commit comments

Comments
 (0)