Skip to content

Commit

Permalink
Introduce support for caching. (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
fr33r authored Oct 3, 2022
1 parent f79a34e commit 339bf8e
Show file tree
Hide file tree
Showing 16 changed files with 522 additions and 94 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ mocks: mocks-v3 mocks-v4

benchmark: bins
@#v4
@cd ./v4 && GO111MODULE=on go test -run XXX -bench . && cd ..
@cd ./v4/internal/benchmark && GO111MODULE=on go test -run XXX -bench . && cd ../../

demo: bins
@docker-compose --file ./docker/docker-compose.yaml up -d
Expand Down
24 changes: 13 additions & 11 deletions v4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,19 @@ u, err := unit.New(opts...)

<p align="center"><img src="https://user-images.githubusercontent.com/5921929/106403546-191daa80-63e4-11eb-98b5-6b5d1989bacb.gif" width="960"></p>

| Name | Type | Description |
| -------------------------------- | ------- | ------------------------------------------------ |
| [_PREFIX._]unit.save.success | counter | The number of successful work unit saves. |
| [_PREFIX._]unit.save | timer | The time duration when saving a work unit. |
| [_PREFIX._]unit.rollback.success | counter | The number of successful work unit rollbacks. |
| [_PREFIX._]unit.rollback.failure | counter | The number of unsuccessful work unit rollbacks. |
| [_PREFIX._]unit.rollback | timer | The time duration when rolling back a work unit. |
| [_PREFIX._]unit.retry.attempt | counter | The number of retry attempts. |
| [_PREFIX._]unit.insert | counter | The number of successful inserts performed. |
| [_PREFIX._]unit.update | counter | The number of successful updates performed. |
| [_PREFIX._]unit.delete | counter | The number of successful deletes performed. |
| Name | Type | Description |
| -------------------------------- | ------- | ------------------------------------------------------------ |
| [_PREFIX._]unit.save.success | counter | The number of successful work unit saves. |
| [_PREFIX._]unit.save | timer | The time duration when saving a work unit. |
| [_PREFIX._]unit.rollback.success | counter | The number of successful work unit rollbacks. |
| [_PREFIX._]unit.rollback.failure | counter | The number of unsuccessful work unit rollbacks. |
| [_PREFIX._]unit.rollback | timer | The time duration when rolling back a work unit. |
| [_PREFIX._]unit.retry.attempt | counter | The number of retry attempts. |
| [_PREFIX._]unit.insert | counter | The number of successful inserts performed. |
| [_PREFIX._]unit.update | counter | The number of successful updates performed. |
| [_PREFIX._]unit.delete | counter | The number of successful deletes performed. |
| [_PREFIX._]unit.cache.insert | counter | The number of registered entities inserted into the cache. |
| [_PREFIX._]unit.cache.delete | counter | The number of registered entities removed from the cache. |

### Uniters
In most circumstances, an application has many aspects that result in the
Expand Down
63 changes: 47 additions & 16 deletions v4/best_effort_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/freerware/work/v4"
"github.com/freerware/work/v4/internal/mock"
"github.com/freerware/work/v4/internal/test"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"
"github.com/uber-go/tally"
Expand Down Expand Up @@ -60,6 +61,10 @@ type BestEffortUnitTestSuite struct {
updateScopeNameWithTags string
deleteScopeName string
deleteScopeNameWithTags string
cacheInsertScopeName string
cacheDeleteScopeName string
cacheInsertScopeNameWithTags string
cacheDeleteScopeNameWithTags string
tags string

// suite state.
Expand Down Expand Up @@ -98,11 +103,15 @@ func (s *BestEffortUnitTestSuite) Setup() {
s.updateScopeNameWithTags = fmt.Sprintf("%s%s%s", s.updateScopeName, sep, s.tags)
s.deleteScopeName = fmt.Sprintf("%s.%s", s.scopePrefix, "unit.delete")
s.deleteScopeNameWithTags = fmt.Sprintf("%s%s%s", s.deleteScopeName, sep, s.tags)
s.cacheInsertScopeName = fmt.Sprintf("%s.%s", s.scopePrefix, "unit.cache.insert")
s.cacheInsertScopeNameWithTags = fmt.Sprintf("%s%s%s", s.cacheInsertScopeName, sep, s.tags)
s.cacheDeleteScopeName = fmt.Sprintf("%s.%s", s.scopePrefix, "unit.cache.delete")
s.cacheDeleteScopeNameWithTags = fmt.Sprintf("%s%s%s", s.cacheDeleteScopeName, sep, s.tags)

// test entities.
foo := Foo{ID: 28}
foo := test.Foo{ID: 28}
fooTypeName := work.TypeNameOf(foo)
bar := Bar{ID: "28"}
bar := test.Bar{ID: "28"}
barTypeName := work.TypeNameOf(bar)

// initialize mocks.
Expand Down Expand Up @@ -141,9 +150,9 @@ func (s *BestEffortUnitTestSuite) SetupTest() {
}

func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
foos := []interface{}{Foo{ID: 28}, Foo{ID: 1992}, Foo{ID: 2}, Foo{ID: 1111}}
bars := []interface{}{Bar{ID: "ID"}, Bar{ID: "1992"}}
fooType, barType := work.TypeNameOf(Foo{}), work.TypeNameOf(Bar{})
foos := []interface{}{test.Foo{ID: 28}, test.Foo{ID: 1992}, test.Foo{ID: 2}, test.Foo{ID: 1111}}
bars := []interface{}{test.Bar{ID: "ID"}, test.Bar{ID: "1992"}}
fooType, barType := work.TypeNameOf(test.Foo{}), work.TypeNameOf(test.Bar{})
return []TableDrivenTest{
{
name: "InsertError",
Expand Down Expand Up @@ -184,9 +193,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -231,9 +242,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("ouch; whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackFailureScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -296,9 +309,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -357,9 +372,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("ouch; whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackFailureScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -430,9 +447,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -499,9 +518,11 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa; ouch"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 2)
s.Len(s.scope.Snapshot().Counters(), 4)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackFailureScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -583,8 +604,10 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
},
ctx: context.Background(),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 1)
s.Len(s.scope.Snapshot().Counters(), 3)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -655,8 +678,10 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 1)
s.Len(s.scope.Snapshot().Counters(), 3)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackFailureScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -733,8 +758,10 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
ctx: context.Background(),
err: errors.New("whoa"),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 1)
s.Len(s.scope.Snapshot().Counters(), 3)
s.Contains(s.scope.Snapshot().Counters(), s.rollbackFailureScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
s.Contains(s.scope.Snapshot().Timers(), s.rollbackScopeNameWithTags)
Expand Down Expand Up @@ -782,11 +809,13 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
},
ctx: context.Background(),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 4)
s.Len(s.scope.Snapshot().Counters(), 6)
s.Contains(s.scope.Snapshot().Counters(), s.saveSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.insertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.updateScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.deleteScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 1)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
},
Expand Down Expand Up @@ -884,12 +913,14 @@ func (s *BestEffortUnitTestSuite) subtests() []TableDrivenTest {
},
ctx: context.Background(),
assertions: func() {
s.Len(s.scope.Snapshot().Counters(), 6)
s.Len(s.scope.Snapshot().Counters(), 8)
s.Contains(s.scope.Snapshot().Counters(), s.saveSuccessScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.retryAttemptScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.insertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.updateScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.deleteScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheInsertScopeNameWithTags)
s.Contains(s.scope.Snapshot().Counters(), s.cacheDeleteScopeNameWithTags)
s.Len(s.scope.Snapshot().Timers(), 2)
s.Contains(s.scope.Snapshot().Timers(), s.saveScopeNameWithTags)
},
Expand Down
22 changes: 22 additions & 0 deletions v4/identifierer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* Copyright 2022 Freerware
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package work

// identifierer represents an object defined by its identity, not by its attributes.
type identifierer interface {
// Identifier retrieves the identity for the object.
Identifier() interface{}
}
22 changes: 22 additions & 0 deletions v4/ider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* Copyright 2022 Freerware
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package work

// ider represents an object defined by its identity, not by its attributes.
type ider interface {
// ider retrieves the identity for the object.
ID() interface{}
}
29 changes: 22 additions & 7 deletions v4/benchmarks_test.go → v4/internal/benchmark/benchmarks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@
* limitations under the License.
*/

package work_test
package work_benchmark

import (
"context"
"testing"

"github.com/freerware/work/v4/internal/test"
"github.com/freerware/work/v4/unit"
)

const EntityCount = 500

func setupEntities() (entities []interface{}) {
for idx := 0; idx < EntityCount; idx++ {
entities = append(entities, Foo{ID: idx})
entities = append(entities, test.Foo{ID: idx})
}
return
}
Expand All @@ -35,7 +36,7 @@ func setupEntities() (entities []interface{}) {
func BenchmarkRegister(b *testing.B) {
entities := setupEntities()
mappers := map[unit.TypeName]unit.DataMapper{
unit.TypeNameOf(Foo{}): NoOpDataMapper{},
unit.TypeNameOf(test.Foo{}): NoOpDataMapper{},
}
b.StopTimer()
b.ResetTimer()
Expand All @@ -56,7 +57,7 @@ func BenchmarkRegister(b *testing.B) {
func BenchmarkAdd(b *testing.B) {
entities := setupEntities()
mappers := map[unit.TypeName]unit.DataMapper{
unit.TypeNameOf(Foo{}): NoOpDataMapper{},
unit.TypeNameOf(test.Foo{}): NoOpDataMapper{},
}
b.StopTimer()
b.ResetTimer()
Expand All @@ -77,7 +78,7 @@ func BenchmarkAdd(b *testing.B) {
func BenchmarkAlter(b *testing.B) {
entities := setupEntities()
mappers := map[unit.TypeName]unit.DataMapper{
unit.TypeNameOf(Foo{}): NoOpDataMapper{},
unit.TypeNameOf(test.Foo{}): NoOpDataMapper{},
}
b.StopTimer()
b.ResetTimer()
Expand All @@ -98,7 +99,7 @@ func BenchmarkAlter(b *testing.B) {
func BenchmarkRemove(b *testing.B) {
entities := setupEntities()
mappers := map[unit.TypeName]unit.DataMapper{
unit.TypeNameOf(Foo{}): NoOpDataMapper{},
unit.TypeNameOf(test.Foo{}): NoOpDataMapper{},
}
b.StopTimer()
b.ResetTimer()
Expand All @@ -119,7 +120,7 @@ func BenchmarkSave(b *testing.B) {
ctx := context.Background()
entities := setupEntities()
mappers := map[unit.TypeName]unit.DataMapper{
unit.TypeNameOf(Foo{}): NoOpDataMapper{},
unit.TypeNameOf(test.Foo{}): NoOpDataMapper{},
}
b.StopTimer()
b.ResetTimer()
Expand Down Expand Up @@ -148,3 +149,17 @@ func BenchmarkSave(b *testing.B) {
}
})
}

type NoOpDataMapper struct{}

func (dm NoOpDataMapper) Insert(ctx context.Context, mCtx unit.MapperContext, e ...interface{}) error {
return nil
}

func (dm NoOpDataMapper) Update(ctx context.Context, mCtx unit.MapperContext, e ...interface{}) error {
return nil
}

func (dm NoOpDataMapper) Delete(ctx context.Context, mCtx unit.MapperContext, e ...interface{}) error {
return nil
}
10 changes: 9 additions & 1 deletion v4/internal/main/metrics_demo.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright 2021 Freerware
/* Copyright 2022 Freerware
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -111,6 +111,14 @@ func main() {
panic(err)
}

registrations := []interface{}{}
for j := 0; j < rand.Intn(maximumEntitiesPerOperation); j++ {
registrations = append(registrations, foo{})
}
if err = unit.Register(registrations...); err != nil {
panic(err)
}

additions := []interface{}{}
for j := 0; j < rand.Intn(maximumEntitiesPerOperation); j++ {
additions = append(additions, foo{})
Expand Down
Loading

0 comments on commit 339bf8e

Please sign in to comment.