Skip to content

Commit

Permalink
First steps in IdentityMap implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Sushkov committed May 31, 2024
1 parent 5e5dccc commit 4d3d77d
Show file tree
Hide file tree
Showing 7 changed files with 390 additions and 63 deletions.
24 changes: 0 additions & 24 deletions grade/internal/infrastructure/seedwork/identity/manageable.go

This file was deleted.

23 changes: 12 additions & 11 deletions grade/internal/infrastructure/seedwork/identity/map.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
package identity

Check failure on line 1 in grade/internal/infrastructure/seedwork/identity/map.go

View workflow job for this annotation

GitHub Actions / lint

: # github.com/emacsway/grade/grade/internal/infrastructure/seedwork/identity [github.com/emacsway/grade/grade/internal/infrastructure/seedwork/identity.test]

import "errors"
import (
"errors"

"github.com/emacsway/grade/grade/pkg/collections"
)

var (
ErrObjectAlreadyWatched = errors.New("")
ErrObjectNotFound = errors.New("")
)

type IdentityMap[K comparable, V any] struct {
manageable cacheMap[K, V]
manageable collections.ReplacingMap[K, V]
isolation IsolationStrategy[K, V]
}

func NewIdentityMap[K comparable, V any]() *IdentityMap[K, V] {
manageable := newCacheMap[K, V]()
func NewIdentityMap[K comparable, V any](size uint) *IdentityMap[K, V] {
manageable := collections.NewReplacingMap[K, V](size)
isolation := serializableStrategy[K, V]{manageable: manageable}

return &IdentityMap[K, V]{
manageable: manageable,
isolation: isolation,
isolation: &isolation,
}
}

func (im *IdentityMap[K, V]) Add(key K, object V) (bool, error) {
im.isolation.add(key, object)

//if _, found := im.objects[key]; found {
// return false, ErrObjectAlreadyWatched
//}
if err := im.isolation.add(key, object); err != nil {
return false, err
}

//im.objects[key] = object
return true, nil
}

Expand Down
61 changes: 33 additions & 28 deletions grade/internal/infrastructure/seedwork/identity/strategy.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package identity

import "errors"
import (
"errors"

"github.com/emacsway/grade/grade/pkg/collections"
)

type IsolationLevel uint

Expand All @@ -11,21 +15,24 @@ const (
Serializable = iota
)

var ErrDeniedOperationForStrategy = errors.New("")
var (
ErrNonexistentObject = errors.New("")
ErrDeniedOperationForStrategy = errors.New("")
)

type IsolationStrategy[K comparable, V any] interface {
add(key K, object V)
add(key K, object V) error
get(key K) (V, error)
has(key K) bool
}

///////

type readUncommittedStrategy[K comparable, V any] struct {
manageable cacheMap[K, V]
manageable collections.ReplacingMap[K, V]
}

func (r *readUncommittedStrategy[K, V]) add(key K, object V) {}
func (r *readUncommittedStrategy[K, V]) add(key K, object V) error {
return nil
}

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

// //
type repeatableReadsStrategy[K comparable, V any] struct {
manageable cacheMap[K, V]
manageable collections.ReplacingMap[K, V]
}

func (r *repeatableReadsStrategy[K, V]) add(key K, object V) {
func (r *repeatableReadsStrategy[K, V]) add(key K, object V) error {
if object != nil {

Check failure on line 56 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / lint

invalid operation: object != nil (mismatched types V and untyped nil)

Check failure on line 56 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.18)

invalid operation: object != nil (mismatched types V and untyped nil)

Check failure on line 56 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.20)

invalid operation: object != nil (mismatched types V and untyped nil)

Check failure on line 56 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.21.x)

invalid operation: object != nil (mismatched types V and untyped nil)
r.manageable.add(key, object)
r.manageable.Add(key, object)
}

return nil
}

func (r *repeatableReadsStrategy[K, V]) get(key K) (V, error) {
object, found := r.manageable.get(key)

return r.manageable.Get(key)
}

func (r *repeatableReadsStrategy[K, V]) has(key K) bool {
return r.manageable.has(key)
return r.manageable.Has(key)
}

// ///
type serializableStrategy[K comparable, V any] struct {
manageable cacheMap[K, V]
manageable collections.ReplacingMap[K, V]
}

func (s serializableStrategy[K, V]) add(key K, object V) {
//TODO implement me
panic("implement me")
}
func (s *serializableStrategy[K, V]) add(key K, object V) error {
if object == nil {

Check failure on line 76 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / lint

invalid operation: object == nil (mismatched types V and untyped nil)

Check failure on line 76 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.18)

invalid operation: object == nil (mismatched types V and untyped nil)

Check failure on line 76 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.20)

invalid operation: object == nil (mismatched types V and untyped nil)

Check failure on line 76 in grade/internal/infrastructure/seedwork/identity/strategy.go

View workflow job for this annotation

GitHub Actions / Execute tests (1.21.x)

invalid operation: object == nil (mismatched types V and untyped nil)
return ErrNonexistentObject
}

func (s serializableStrategy[K, V]) get(key K) (V, error) {
//obj = self._identity_map().do_get(key)
//if isinstance(obj, NonexistentObject):
//raise ObjectDoesNotExist()
//return obj
s.manageable.Add(key, object)
return nil
}

s.manageable.get(ke)
func (s *serializableStrategy[K, V]) get(key K) (V, error) {
return s.manageable.Get(key)
}

func (s serializableStrategy[K, V]) has(key K) bool {
return s.manageable.has(key)
func (s *serializableStrategy[K, V]) has(key K) bool {
return s.manageable.Has(key)
}
52 changes: 52 additions & 0 deletions grade/pkg/cache/lru.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cache

import (
"container/list"
)

type Lru[T comparable] struct {
items map[T]*list.Element
order *list.List
size uint
}

func NewLru[T comparable](size uint) Lru[T] {
return Lru[T]{
items: make(map[T]*list.Element, size),
order: list.New(),
size: size,
}
}

func (l *Lru[T]) Add(value T) {
order := l.order.PushBack(&value)
l.items[value] = order

if (uint)(len(l.items)) > l.size {

Check failure on line 25 in grade/pkg/cache/lru.go

View workflow job for this annotation

GitHub Actions / lint

typeUnparen: could simplify (uint) to uint (gocritic)
order = l.order.Front()
l.order.Remove(order)

delete(l.items, order.Value.(T))
}
}

func (l *Lru[T]) Touch(value T) {
order := l.items[value]
l.order.MoveToBack(order)
}

func (l *Lru[T]) Remove(value T) {
order := l.items[value]

delete(l.items, value)
l.order.Remove(order)
}

func (l *Lru[T]) Clear() {
l.order = list.New()
l.items = make(map[T]*list.Element, l.size)
}

func (l *Lru[T]) SetSize(size uint) {
l.size = size
}
17 changes: 17 additions & 0 deletions grade/pkg/cache/lru_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cache

import "testing"

func TestLru(t *testing.T) {

lru := NewLru[string](2)

//lru.Add("1")

Check failure on line 9 in grade/pkg/cache/lru_test.go

View workflow job for this annotation

GitHub Actions / lint

commentFormatting: put a space between `//` and comment text (gocritic)
//lru.Add("2")
lru.Add("3")
lru.Add("2")
lru.Add("1")

//lru.Touch("3")

Check failure on line 15 in grade/pkg/cache/lru_test.go

View workflow job for this annotation

GitHub Actions / lint

commentFormatting: put a space between `//` and comment text (gocritic)
//lru.Add("3")
}
103 changes: 103 additions & 0 deletions grade/pkg/collections/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package collections

import (
"container/list"
"errors"
)

var (
ErrKeyDoesNotContains = errors.New("")
)

type CachedMap[K comparable, V any] struct {
m map[K]V
}

func NewCachedMap[K comparable, V any]() CachedMap[K, V] {
return CachedMap[K, V]{
m: map[K]V{},
}
}

func (m CachedMap[K, V]) Add(key K, value V) {
m.m[key] = value
}

func (m CachedMap[K, V]) Get(key K) (value V, err error) {
if value, found := m.m[key]; found {
return value, nil
}

return value, ErrKeyDoesNotContains
}

func (m CachedMap[K, V]) Remove(key K) {
delete(m.m, key)
}

func (m CachedMap[K, V]) Has(key K) bool {
_, found := m.m[key]
return found
}

type item[K comparable, V any] struct {
key K
value V
}

type ReplacingMap[K comparable, V any] struct {
items map[K]*list.Element
order *list.List
size uint
}

func NewReplacingMap[K comparable, V any](size uint) ReplacingMap[K, V] {
return ReplacingMap[K, V]{
items: make(map[K]*list.Element, size),
order: list.New(),
size: size,
}
}

func (m *ReplacingMap[K, V]) Add(key K, value V) {
element := m.order.PushBack(item[K, V]{key, value})
m.items[key] = element

if (uint)(len(m.items)) > m.size {

Check failure on line 66 in grade/pkg/collections/map.go

View workflow job for this annotation

GitHub Actions / lint

typeUnparen: could simplify (uint) to uint (gocritic)
element = m.order.Front()
m.order.Remove(element)
delete(m.items, element.Value.(item[K, V]).key)
}
}

func (m *ReplacingMap[K, V]) Get(key K) (value V, err error) {
if element, found := m.items[key]; found {
return element.Value.(item[K, V]).value, nil
}

return value, ErrKeyDoesNotContains
}

func (m *ReplacingMap[K, V]) Touch(key K) {
element := m.items[key]
m.order.MoveToBack(element)
}

func (m *ReplacingMap[K, V]) Remove(key K) {
element, found := m.items[key]
if !found {
return
}

delete(m.items, key)
m.order.Remove(element)
}

func (m *ReplacingMap[K, V]) Has(key K) bool {
_, found := m.items[key]
return found
}

func (m *ReplacingMap[K, V]) SetSize(size uint) {
m.size = size
}
Loading

0 comments on commit 4d3d77d

Please sign in to comment.