Skip to content

Commit 4d3d77d

Browse files
author
Ivan Sushkov
committed
First steps in IdentityMap implementation
1 parent 5e5dccc commit 4d3d77d

File tree

7 files changed

+390
-63
lines changed

7 files changed

+390
-63
lines changed

grade/internal/infrastructure/seedwork/identity/manageable.go

-24
This file was deleted.

grade/internal/infrastructure/seedwork/identity/map.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
11
package identity
22

3-
import "errors"
3+
import (
4+
"errors"
5+
6+
"github.com/emacsway/grade/grade/pkg/collections"
7+
)
48

59
var (
610
ErrObjectAlreadyWatched = errors.New("")
711
ErrObjectNotFound = errors.New("")
812
)
913

1014
type IdentityMap[K comparable, V any] struct {
11-
manageable cacheMap[K, V]
15+
manageable collections.ReplacingMap[K, V]
1216
isolation IsolationStrategy[K, V]
1317
}
1418

15-
func NewIdentityMap[K comparable, V any]() *IdentityMap[K, V] {
16-
manageable := newCacheMap[K, V]()
19+
func NewIdentityMap[K comparable, V any](size uint) *IdentityMap[K, V] {
20+
manageable := collections.NewReplacingMap[K, V](size)
1721
isolation := serializableStrategy[K, V]{manageable: manageable}
1822

1923
return &IdentityMap[K, V]{
2024
manageable: manageable,
21-
isolation: isolation,
25+
isolation: &isolation,
2226
}
2327
}
2428

2529
func (im *IdentityMap[K, V]) Add(key K, object V) (bool, error) {
26-
im.isolation.add(key, object)
27-
28-
//if _, found := im.objects[key]; found {
29-
// return false, ErrObjectAlreadyWatched
30-
//}
30+
if err := im.isolation.add(key, object); err != nil {
31+
return false, err
32+
}
3133

32-
//im.objects[key] = object
3334
return true, nil
3435
}
3536

Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package identity
22

3-
import "errors"
3+
import (
4+
"errors"
5+
6+
"github.com/emacsway/grade/grade/pkg/collections"
7+
)
48

59
type IsolationLevel uint
610

@@ -11,21 +15,24 @@ const (
1115
Serializable = iota
1216
)
1317

14-
var ErrDeniedOperationForStrategy = errors.New("")
18+
var (
19+
ErrNonexistentObject = errors.New("")
20+
ErrDeniedOperationForStrategy = errors.New("")
21+
)
1522

1623
type IsolationStrategy[K comparable, V any] interface {
17-
add(key K, object V)
24+
add(key K, object V) error
1825
get(key K) (V, error)
1926
has(key K) bool
2027
}
2128

22-
///////
23-
2429
type readUncommittedStrategy[K comparable, V any] struct {
25-
manageable cacheMap[K, V]
30+
manageable collections.ReplacingMap[K, V]
2631
}
2732

28-
func (r *readUncommittedStrategy[K, V]) add(key K, object V) {}
33+
func (r *readUncommittedStrategy[K, V]) add(key K, object V) error {
34+
return nil
35+
}
2936

3037
func (r *readUncommittedStrategy[K, V]) get(key K) (object V, err error) {
3138
return object, ErrDeniedOperationForStrategy
@@ -41,45 +48,43 @@ type readCommittedStrategy[K comparable, V any] struct {
4148
readUncommittedStrategy[K, V]
4249
}
4350

44-
// //
4551
type repeatableReadsStrategy[K comparable, V any] struct {
46-
manageable cacheMap[K, V]
52+
manageable collections.ReplacingMap[K, V]
4753
}
4854

49-
func (r *repeatableReadsStrategy[K, V]) add(key K, object V) {
55+
func (r *repeatableReadsStrategy[K, V]) add(key K, object V) error {
5056
if object != nil {
51-
r.manageable.add(key, object)
57+
r.manageable.Add(key, object)
5258
}
59+
60+
return nil
5361
}
5462

5563
func (r *repeatableReadsStrategy[K, V]) get(key K) (V, error) {
56-
object, found := r.manageable.get(key)
57-
64+
return r.manageable.Get(key)
5865
}
5966

6067
func (r *repeatableReadsStrategy[K, V]) has(key K) bool {
61-
return r.manageable.has(key)
68+
return r.manageable.Has(key)
6269
}
6370

64-
// ///
6571
type serializableStrategy[K comparable, V any] struct {
66-
manageable cacheMap[K, V]
72+
manageable collections.ReplacingMap[K, V]
6773
}
6874

69-
func (s serializableStrategy[K, V]) add(key K, object V) {
70-
//TODO implement me
71-
panic("implement me")
72-
}
75+
func (s *serializableStrategy[K, V]) add(key K, object V) error {
76+
if object == nil {
77+
return ErrNonexistentObject
78+
}
7379

74-
func (s serializableStrategy[K, V]) get(key K) (V, error) {
75-
//obj = self._identity_map().do_get(key)
76-
//if isinstance(obj, NonexistentObject):
77-
//raise ObjectDoesNotExist()
78-
//return obj
80+
s.manageable.Add(key, object)
81+
return nil
82+
}
7983

80-
s.manageable.get(ke)
84+
func (s *serializableStrategy[K, V]) get(key K) (V, error) {
85+
return s.manageable.Get(key)
8186
}
8287

83-
func (s serializableStrategy[K, V]) has(key K) bool {
84-
return s.manageable.has(key)
88+
func (s *serializableStrategy[K, V]) has(key K) bool {
89+
return s.manageable.Has(key)
8590
}

grade/pkg/cache/lru.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package cache
2+
3+
import (
4+
"container/list"
5+
)
6+
7+
type Lru[T comparable] struct {
8+
items map[T]*list.Element
9+
order *list.List
10+
size uint
11+
}
12+
13+
func NewLru[T comparable](size uint) Lru[T] {
14+
return Lru[T]{
15+
items: make(map[T]*list.Element, size),
16+
order: list.New(),
17+
size: size,
18+
}
19+
}
20+
21+
func (l *Lru[T]) Add(value T) {
22+
order := l.order.PushBack(&value)
23+
l.items[value] = order
24+
25+
if (uint)(len(l.items)) > l.size {
26+
order = l.order.Front()
27+
l.order.Remove(order)
28+
29+
delete(l.items, order.Value.(T))
30+
}
31+
}
32+
33+
func (l *Lru[T]) Touch(value T) {
34+
order := l.items[value]
35+
l.order.MoveToBack(order)
36+
}
37+
38+
func (l *Lru[T]) Remove(value T) {
39+
order := l.items[value]
40+
41+
delete(l.items, value)
42+
l.order.Remove(order)
43+
}
44+
45+
func (l *Lru[T]) Clear() {
46+
l.order = list.New()
47+
l.items = make(map[T]*list.Element, l.size)
48+
}
49+
50+
func (l *Lru[T]) SetSize(size uint) {
51+
l.size = size
52+
}

grade/pkg/cache/lru_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package cache
2+
3+
import "testing"
4+
5+
func TestLru(t *testing.T) {
6+
7+
lru := NewLru[string](2)
8+
9+
//lru.Add("1")
10+
//lru.Add("2")
11+
lru.Add("3")
12+
lru.Add("2")
13+
lru.Add("1")
14+
15+
//lru.Touch("3")
16+
//lru.Add("3")
17+
}

grade/pkg/collections/map.go

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package collections
2+
3+
import (
4+
"container/list"
5+
"errors"
6+
)
7+
8+
var (
9+
ErrKeyDoesNotContains = errors.New("")
10+
)
11+
12+
type CachedMap[K comparable, V any] struct {
13+
m map[K]V
14+
}
15+
16+
func NewCachedMap[K comparable, V any]() CachedMap[K, V] {
17+
return CachedMap[K, V]{
18+
m: map[K]V{},
19+
}
20+
}
21+
22+
func (m CachedMap[K, V]) Add(key K, value V) {
23+
m.m[key] = value
24+
}
25+
26+
func (m CachedMap[K, V]) Get(key K) (value V, err error) {
27+
if value, found := m.m[key]; found {
28+
return value, nil
29+
}
30+
31+
return value, ErrKeyDoesNotContains
32+
}
33+
34+
func (m CachedMap[K, V]) Remove(key K) {
35+
delete(m.m, key)
36+
}
37+
38+
func (m CachedMap[K, V]) Has(key K) bool {
39+
_, found := m.m[key]
40+
return found
41+
}
42+
43+
type item[K comparable, V any] struct {
44+
key K
45+
value V
46+
}
47+
48+
type ReplacingMap[K comparable, V any] struct {
49+
items map[K]*list.Element
50+
order *list.List
51+
size uint
52+
}
53+
54+
func NewReplacingMap[K comparable, V any](size uint) ReplacingMap[K, V] {
55+
return ReplacingMap[K, V]{
56+
items: make(map[K]*list.Element, size),
57+
order: list.New(),
58+
size: size,
59+
}
60+
}
61+
62+
func (m *ReplacingMap[K, V]) Add(key K, value V) {
63+
element := m.order.PushBack(item[K, V]{key, value})
64+
m.items[key] = element
65+
66+
if (uint)(len(m.items)) > m.size {
67+
element = m.order.Front()
68+
m.order.Remove(element)
69+
delete(m.items, element.Value.(item[K, V]).key)
70+
}
71+
}
72+
73+
func (m *ReplacingMap[K, V]) Get(key K) (value V, err error) {
74+
if element, found := m.items[key]; found {
75+
return element.Value.(item[K, V]).value, nil
76+
}
77+
78+
return value, ErrKeyDoesNotContains
79+
}
80+
81+
func (m *ReplacingMap[K, V]) Touch(key K) {
82+
element := m.items[key]
83+
m.order.MoveToBack(element)
84+
}
85+
86+
func (m *ReplacingMap[K, V]) Remove(key K) {
87+
element, found := m.items[key]
88+
if !found {
89+
return
90+
}
91+
92+
delete(m.items, key)
93+
m.order.Remove(element)
94+
}
95+
96+
func (m *ReplacingMap[K, V]) Has(key K) bool {
97+
_, found := m.items[key]
98+
return found
99+
}
100+
101+
func (m *ReplacingMap[K, V]) SetSize(size uint) {
102+
m.size = size
103+
}

0 commit comments

Comments
 (0)