Merge pull request #47 from anytypeio/update-proto
This commit is contained in:
commit
1fbf87995b
120
app/ocache/entry.go
Normal file
120
app/ocache/entry.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package ocache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type entryState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
entryStateLoading = iota
|
||||||
|
entryStateActive
|
||||||
|
entryStateClosing
|
||||||
|
entryStateClosed
|
||||||
|
)
|
||||||
|
|
||||||
|
type entry struct {
|
||||||
|
id string
|
||||||
|
state entryState
|
||||||
|
lastUsage time.Time
|
||||||
|
load chan struct{}
|
||||||
|
loadErr error
|
||||||
|
value Object
|
||||||
|
close chan struct{}
|
||||||
|
mx sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEntry(id string, value Object, state entryState) *entry {
|
||||||
|
return &entry{
|
||||||
|
id: id,
|
||||||
|
load: make(chan struct{}),
|
||||||
|
lastUsage: time.Now(),
|
||||||
|
state: state,
|
||||||
|
value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) isActive() bool {
|
||||||
|
e.mx.Lock()
|
||||||
|
defer e.mx.Unlock()
|
||||||
|
return e.state == entryStateActive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) isClosing() bool {
|
||||||
|
e.mx.Lock()
|
||||||
|
defer e.mx.Unlock()
|
||||||
|
return e.state == entryStateClosed || e.state == entryStateClosing
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) waitLoad(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.DebugCtx(ctx, "ctx done while waiting on object load", zap.String("id", id))
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case <-e.load:
|
||||||
|
return e.value, e.loadErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) waitClose(ctx context.Context, id string) (res bool, err error) {
|
||||||
|
e.mx.Lock()
|
||||||
|
switch e.state {
|
||||||
|
case entryStateClosing:
|
||||||
|
waitCh := e.close
|
||||||
|
e.mx.Unlock()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.DebugCtx(ctx, "ctx done while waiting on object close", zap.String("id", id))
|
||||||
|
return false, ctx.Err()
|
||||||
|
case <-waitCh:
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
case entryStateClosed:
|
||||||
|
e.mx.Unlock()
|
||||||
|
return true, nil
|
||||||
|
default:
|
||||||
|
e.mx.Unlock()
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) setClosing(wait bool) (prevState, curState entryState) {
|
||||||
|
e.mx.Lock()
|
||||||
|
prevState = e.state
|
||||||
|
curState = e.state
|
||||||
|
if e.state == entryStateClosing {
|
||||||
|
waitCh := e.close
|
||||||
|
e.mx.Unlock()
|
||||||
|
if !wait {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
<-waitCh
|
||||||
|
e.mx.Lock()
|
||||||
|
}
|
||||||
|
if e.state != entryStateClosed {
|
||||||
|
e.state = entryStateClosing
|
||||||
|
e.close = make(chan struct{})
|
||||||
|
}
|
||||||
|
curState = e.state
|
||||||
|
e.mx.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) setActive(chClose bool) {
|
||||||
|
e.mx.Lock()
|
||||||
|
defer e.mx.Unlock()
|
||||||
|
if chClose {
|
||||||
|
close(e.close)
|
||||||
|
}
|
||||||
|
e.state = entryStateActive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *entry) setClosed() {
|
||||||
|
e.mx.Lock()
|
||||||
|
defer e.mx.Unlock()
|
||||||
|
close(e.close)
|
||||||
|
e.state = entryStateClosed
|
||||||
|
}
|
||||||
@ -44,12 +44,6 @@ var WithGCPeriod = func(gcPeriod time.Duration) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var WithRefCounter = func(enable bool) Option {
|
|
||||||
return func(cache *oCache) {
|
|
||||||
cache.refCounter = enable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(loadFunc LoadFunc, opts ...Option) OCache {
|
func New(loadFunc LoadFunc, opts ...Option) OCache {
|
||||||
c := &oCache{
|
c := &oCache{
|
||||||
data: make(map[string]*entry),
|
data: make(map[string]*entry),
|
||||||
@ -73,33 +67,7 @@ func New(loadFunc LoadFunc, opts ...Option) OCache {
|
|||||||
|
|
||||||
type Object interface {
|
type Object interface {
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
}
|
TryClose(objectTTL time.Duration) (res bool, err error)
|
||||||
|
|
||||||
type ObjectLocker interface {
|
|
||||||
Object
|
|
||||||
Locked() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type ObjectLastUsage interface {
|
|
||||||
LastUsage() time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
type entry struct {
|
|
||||||
id string
|
|
||||||
lastUsage time.Time
|
|
||||||
refCount uint32
|
|
||||||
isClosing bool
|
|
||||||
load chan struct{}
|
|
||||||
loadErr error
|
|
||||||
value Object
|
|
||||||
close chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *entry) locked() bool {
|
|
||||||
if locker, ok := e.value.(ObjectLocker); ok {
|
|
||||||
return locker.Locked()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type OCache interface {
|
type OCache interface {
|
||||||
@ -116,12 +84,8 @@ type OCache interface {
|
|||||||
// Add adds new object to cache
|
// Add adds new object to cache
|
||||||
// Returns error when object exists
|
// Returns error when object exists
|
||||||
Add(id string, value Object) (err error)
|
Add(id string, value Object) (err error)
|
||||||
// Release decreases the refs counter
|
|
||||||
Release(id string) bool
|
|
||||||
// Reset sets refs counter to 0
|
|
||||||
Reset(id string) bool
|
|
||||||
// Remove closes and removes object
|
// Remove closes and removes object
|
||||||
Remove(id string) (ok bool, err error)
|
Remove(ctx context.Context, id string) (ok bool, err error)
|
||||||
// ForEach iterates over all loaded objects, breaks when callback returns false
|
// ForEach iterates over all loaded objects, breaks when callback returns false
|
||||||
ForEach(f func(v Object) (isContinue bool))
|
ForEach(f func(v Object) (isContinue bool))
|
||||||
// GC frees not used and expired objects
|
// GC frees not used and expired objects
|
||||||
@ -134,17 +98,16 @@ type OCache interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type oCache struct {
|
type oCache struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
data map[string]*entry
|
data map[string]*entry
|
||||||
loadFunc LoadFunc
|
loadFunc LoadFunc
|
||||||
timeNow func() time.Time
|
timeNow func() time.Time
|
||||||
ttl time.Duration
|
ttl time.Duration
|
||||||
gc time.Duration
|
gc time.Duration
|
||||||
closed bool
|
closed bool
|
||||||
closeCh chan struct{}
|
closeCh chan struct{}
|
||||||
log *zap.SugaredLogger
|
log *zap.SugaredLogger
|
||||||
metrics *metrics
|
metrics *metrics
|
||||||
refCounter bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
|
func (c *oCache) Get(ctx context.Context, id string) (value Object, err error) {
|
||||||
@ -160,69 +123,36 @@ Load:
|
|||||||
return nil, ErrClosed
|
return nil, ErrClosed
|
||||||
}
|
}
|
||||||
if e, ok = c.data[id]; !ok {
|
if e, ok = c.data[id]; !ok {
|
||||||
|
e = newEntry(id, nil, entryStateLoading)
|
||||||
load = true
|
load = true
|
||||||
e = &entry{
|
|
||||||
id: id,
|
|
||||||
load: make(chan struct{}),
|
|
||||||
}
|
|
||||||
c.data[id] = e
|
c.data[id] = e
|
||||||
}
|
}
|
||||||
closing := e.isClosing
|
e.lastUsage = time.Now()
|
||||||
if !e.isClosing {
|
|
||||||
e.lastUsage = c.timeNow()
|
|
||||||
if c.refCounter {
|
|
||||||
e.refCount++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
if closing {
|
reload, err := e.waitClose(ctx, id)
|
||||||
select {
|
if err != nil {
|
||||||
case <-ctx.Done():
|
return nil, err
|
||||||
log.DebugCtx(ctx, "ctx done while waiting on object close", zap.String("id", id))
|
}
|
||||||
return nil, ctx.Err()
|
if reload {
|
||||||
case <-e.close:
|
goto Load
|
||||||
goto Load
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if load {
|
if load {
|
||||||
go c.load(ctx, id, e)
|
go c.load(ctx, id, e)
|
||||||
}
|
}
|
||||||
if c.metrics != nil {
|
c.metricsGet(!load)
|
||||||
if load {
|
return e.waitLoad(ctx, id)
|
||||||
c.metrics.miss.Inc()
|
|
||||||
} else {
|
|
||||||
c.metrics.hit.Inc()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
log.DebugCtx(ctx, "ctx done while waiting on object load", zap.String("id", id))
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case <-e.load:
|
|
||||||
}
|
|
||||||
return e.value, e.loadErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) Pick(ctx context.Context, id string) (value Object, err error) {
|
func (c *oCache) Pick(ctx context.Context, id string) (value Object, err error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
val, ok := c.data[id]
|
val, ok := c.data[id]
|
||||||
if !ok || val.isClosing {
|
if !ok || val.isClosing() {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
return nil, ErrNotExists
|
return nil, ErrNotExists
|
||||||
}
|
}
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
c.metricsGet(true)
|
||||||
if c.metrics != nil {
|
return val.waitLoad(ctx, id)
|
||||||
c.metrics.hit.Inc()
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case <-val.load:
|
|
||||||
return val.value, val.loadErr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) load(ctx context.Context, id string, e *entry) {
|
func (c *oCache) load(ctx context.Context, id string, e *entry) {
|
||||||
@ -236,63 +166,39 @@ func (c *oCache) load(ctx context.Context, id string, e *entry) {
|
|||||||
delete(c.data, id)
|
delete(c.data, id)
|
||||||
} else {
|
} else {
|
||||||
e.value = value
|
e.value = value
|
||||||
|
e.setActive(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) Release(id string) bool {
|
func (c *oCache) Remove(ctx context.Context, id string) (ok bool, err error) {
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
if c.closed {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if e, ok := c.data[id]; ok {
|
|
||||||
if c.refCounter && e.refCount > 0 {
|
|
||||||
e.refCount--
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *oCache) Reset(id string) bool {
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
if c.closed {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if e, ok := c.data[id]; ok {
|
|
||||||
e.refCount = 0
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *oCache) Remove(id string) (ok bool, err error) {
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
if c.closed {
|
if c.closed {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
err = ErrClosed
|
err = ErrClosed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var e *entry
|
e, ok := c.data[id]
|
||||||
e, ok = c.data[id]
|
if !ok {
|
||||||
if !ok || e.isClosing {
|
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
return
|
return false, ErrNotExists
|
||||||
}
|
}
|
||||||
e.isClosing = true
|
|
||||||
e.close = make(chan struct{})
|
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
return c.remove(ctx, e)
|
||||||
|
}
|
||||||
|
|
||||||
<-e.load
|
func (c *oCache) remove(ctx context.Context, e *entry) (ok bool, err error) {
|
||||||
if e.value != nil {
|
if _, err = e.waitLoad(ctx, e.id); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
_, curState := e.setClosing(true)
|
||||||
|
if curState == entryStateClosing {
|
||||||
|
ok = true
|
||||||
err = e.value.Close()
|
err = e.value.Close()
|
||||||
|
c.mu.Lock()
|
||||||
|
e.setClosed()
|
||||||
|
delete(c.data, e.id)
|
||||||
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
c.mu.Lock()
|
|
||||||
close(e.close)
|
|
||||||
delete(c.data, e.id)
|
|
||||||
c.mu.Unlock()
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,13 +220,7 @@ func (c *oCache) Add(id string, value Object) (err error) {
|
|||||||
if _, ok := c.data[id]; ok {
|
if _, ok := c.data[id]; ok {
|
||||||
return ErrExists
|
return ErrExists
|
||||||
}
|
}
|
||||||
e := &entry{
|
e := newEntry(id, value, entryStateActive)
|
||||||
id: id,
|
|
||||||
lastUsage: time.Now(),
|
|
||||||
refCount: 0,
|
|
||||||
load: make(chan struct{}),
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
close(e.load)
|
close(e.load)
|
||||||
c.data[id] = e
|
c.data[id] = e
|
||||||
return
|
return
|
||||||
@ -332,7 +232,7 @@ func (c *oCache) ForEach(f func(obj Object) (isContinue bool)) {
|
|||||||
for _, v := range c.data {
|
for _, v := range c.data {
|
||||||
select {
|
select {
|
||||||
case <-v.load:
|
case <-v.load:
|
||||||
if v.value != nil && !v.isClosing {
|
if v.value != nil && !v.isClosing() {
|
||||||
objects = append(objects, v.value)
|
objects = append(objects, v.value)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -368,40 +268,35 @@ func (c *oCache) GC() {
|
|||||||
deadline := c.timeNow().Add(-c.ttl)
|
deadline := c.timeNow().Add(-c.ttl)
|
||||||
var toClose []*entry
|
var toClose []*entry
|
||||||
for _, e := range c.data {
|
for _, e := range c.data {
|
||||||
if e.isClosing {
|
if e.isActive() && e.lastUsage.Before(deadline) {
|
||||||
continue
|
|
||||||
}
|
|
||||||
lu := e.lastUsage
|
|
||||||
if lug, ok := e.value.(ObjectLastUsage); ok {
|
|
||||||
lu = lug.LastUsage()
|
|
||||||
}
|
|
||||||
if !e.locked() && e.refCount <= 0 && lu.Before(deadline) {
|
|
||||||
e.isClosing = true
|
|
||||||
e.close = make(chan struct{})
|
e.close = make(chan struct{})
|
||||||
toClose = append(toClose, e)
|
toClose = append(toClose, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size := len(c.data)
|
size := len(c.data)
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
closedNum := 0
|
||||||
for _, e := range toClose {
|
for _, e := range toClose {
|
||||||
<-e.load
|
prevState, _ := e.setClosing(false)
|
||||||
if e.value != nil {
|
if prevState == entryStateClosing || prevState == entryStateClosed {
|
||||||
if err := e.value.Close(); err != nil {
|
continue
|
||||||
c.log.With("object_id", e.id).Warnf("GC: object close error: %v", err)
|
}
|
||||||
}
|
closed, err := e.value.TryClose(c.ttl)
|
||||||
|
if err != nil {
|
||||||
|
c.log.With("object_id", e.id).Warnf("GC: object close error: %v", err)
|
||||||
|
}
|
||||||
|
if !closed {
|
||||||
|
e.setActive(true)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
closedNum++
|
||||||
|
c.mu.Lock()
|
||||||
|
e.setClosed()
|
||||||
|
delete(c.data, e.id)
|
||||||
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.log.Infof("GC: removed %d; cache size: %d", len(toClose), size)
|
c.metricsClosed(closedNum, size)
|
||||||
if len(toClose) > 0 && c.metrics != nil {
|
|
||||||
c.metrics.gc.Add(float64(len(toClose)))
|
|
||||||
}
|
|
||||||
c.mu.Lock()
|
|
||||||
for _, e := range toClose {
|
|
||||||
close(e.close)
|
|
||||||
delete(c.data, e.id)
|
|
||||||
}
|
|
||||||
c.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oCache) Len() int {
|
func (c *oCache) Len() int {
|
||||||
@ -418,25 +313,34 @@ func (c *oCache) Close() (err error) {
|
|||||||
}
|
}
|
||||||
c.closed = true
|
c.closed = true
|
||||||
close(c.closeCh)
|
close(c.closeCh)
|
||||||
var toClose, alreadyClosing []*entry
|
var toClose []*entry
|
||||||
for _, e := range c.data {
|
for _, e := range c.data {
|
||||||
if e.isClosing {
|
toClose = append(toClose, e)
|
||||||
alreadyClosing = append(alreadyClosing, e)
|
|
||||||
} else {
|
|
||||||
toClose = append(toClose, e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
for _, e := range toClose {
|
for _, e := range toClose {
|
||||||
<-e.load
|
if _, err := c.remove(context.Background(), e); err != nil && err != ErrNotExists {
|
||||||
if e.value != nil {
|
c.log.With("object_id", e.id).Warnf("cache close: object close error: %v", err)
|
||||||
if clErr := e.value.Close(); clErr != nil {
|
|
||||||
c.log.With("object_id", e.id).Warnf("cache close: object close error: %v", clErr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, e := range alreadyClosing {
|
|
||||||
<-e.close
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *oCache) metricsGet(hit bool) {
|
||||||
|
if c.metrics == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if hit {
|
||||||
|
c.metrics.hit.Inc()
|
||||||
|
} else {
|
||||||
|
c.metrics.miss.Inc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *oCache) metricsClosed(closedLen, size int) {
|
||||||
|
c.log.Infof("GC: removed %d; cache size: %d", closedLen, size)
|
||||||
|
if c.metrics == nil || closedLen == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.metrics.gc.Add(float64(closedLen))
|
||||||
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ package ocache
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -11,26 +13,48 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ctx = context.Background()
|
||||||
|
|
||||||
type testObject struct {
|
type testObject struct {
|
||||||
name string
|
name string
|
||||||
closeErr error
|
closeErr error
|
||||||
closeCh chan struct{}
|
closeCh chan struct{}
|
||||||
|
tryReturn bool
|
||||||
|
closeCalled bool
|
||||||
|
tryCloseCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestObject(name string, closeCh chan struct{}) *testObject {
|
func NewTestObject(name string, tryReturn bool, closeCh chan struct{}) *testObject {
|
||||||
return &testObject{
|
return &testObject{
|
||||||
name: name,
|
name: name,
|
||||||
closeCh: closeCh,
|
closeCh: closeCh,
|
||||||
|
tryReturn: tryReturn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testObject) Close() (err error) {
|
func (t *testObject) Close() (err error) {
|
||||||
|
if t.closeCalled || (t.tryCloseCalled && t.tryReturn) {
|
||||||
|
panic("close called twice")
|
||||||
|
}
|
||||||
|
t.closeCalled = true
|
||||||
if t.closeCh != nil {
|
if t.closeCh != nil {
|
||||||
<-t.closeCh
|
<-t.closeCh
|
||||||
}
|
}
|
||||||
return t.closeErr
|
return t.closeErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *testObject) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||||
|
if t.closeCalled || (t.tryCloseCalled && t.tryReturn) {
|
||||||
|
panic("close called twice")
|
||||||
|
}
|
||||||
|
t.tryCloseCalled = true
|
||||||
|
if t.closeCh != nil {
|
||||||
|
<-t.closeCh
|
||||||
|
return t.tryReturn, t.closeErr
|
||||||
|
}
|
||||||
|
return t.tryReturn, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestOCache_Get(t *testing.T) {
|
func TestOCache_Get(t *testing.T) {
|
||||||
t.Run("successful", func(t *testing.T) {
|
t.Run("successful", func(t *testing.T) {
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
@ -116,42 +140,37 @@ func TestOCache_Get(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOCache_GC(t *testing.T) {
|
func TestOCache_GC(t *testing.T) {
|
||||||
t.Run("test without close wait", func(t *testing.T) {
|
t.Run("test gc expired object", func(t *testing.T) {
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return &testObject{name: id}, nil
|
return NewTestObject(id, true, nil), nil
|
||||||
}, WithTTL(time.Millisecond*10), WithRefCounter(true))
|
}, WithTTL(time.Millisecond*10))
|
||||||
val, err := c.Get(context.TODO(), "id")
|
val, err := c.Get(context.TODO(), "id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
assert.Equal(t, 1, c.Len())
|
assert.Equal(t, 1, c.Len())
|
||||||
c.GC()
|
c.GC()
|
||||||
assert.Equal(t, 1, c.Len())
|
assert.Equal(t, 1, c.Len())
|
||||||
time.Sleep(time.Millisecond * 30)
|
time.Sleep(time.Millisecond * 20)
|
||||||
c.GC()
|
|
||||||
assert.Equal(t, 1, c.Len())
|
|
||||||
assert.True(t, c.Release("id"))
|
|
||||||
c.GC()
|
c.GC()
|
||||||
assert.Equal(t, 0, c.Len())
|
assert.Equal(t, 0, c.Len())
|
||||||
assert.False(t, c.Release("id"))
|
|
||||||
})
|
})
|
||||||
t.Run("test with close wait", func(t *testing.T) {
|
t.Run("test gc tryClose true, close before get", func(t *testing.T) {
|
||||||
closeCh := make(chan struct{})
|
closeCh := make(chan struct{})
|
||||||
getCh := make(chan struct{})
|
getCh := make(chan struct{})
|
||||||
|
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
return NewTestObject(id, closeCh), nil
|
return NewTestObject(id, true, closeCh), nil
|
||||||
}, WithTTL(time.Millisecond*10), WithRefCounter(true))
|
}, WithTTL(time.Millisecond*10))
|
||||||
val, err := c.Get(context.TODO(), "id")
|
val, err := c.Get(context.TODO(), "id")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
assert.Equal(t, 1, c.Len())
|
assert.Equal(t, 1, c.Len())
|
||||||
assert.True(t, c.Release("id"))
|
|
||||||
// making ttl pass
|
// making ttl pass
|
||||||
time.Sleep(time.Millisecond * 40)
|
time.Sleep(time.Millisecond * 20)
|
||||||
// first gc will be run after 20 secs, so calling it manually
|
// first gc will be run after 20 secs, so calling it manually
|
||||||
go c.GC()
|
go c.GC()
|
||||||
// waiting until all objects are marked as closing
|
// waiting until all objects are marked as closing
|
||||||
time.Sleep(time.Millisecond * 40)
|
time.Sleep(time.Millisecond * 20)
|
||||||
var events []string
|
var events []string
|
||||||
go func() {
|
go func() {
|
||||||
_, err := c.Get(context.TODO(), "id")
|
_, err := c.Get(context.TODO(), "id")
|
||||||
@ -160,47 +179,313 @@ func TestOCache_GC(t *testing.T) {
|
|||||||
events = append(events, "get")
|
events = append(events, "get")
|
||||||
close(getCh)
|
close(getCh)
|
||||||
}()
|
}()
|
||||||
events = append(events, "close")
|
|
||||||
// sleeping to make sure that Get is called
|
// sleeping to make sure that Get is called
|
||||||
time.Sleep(time.Millisecond * 40)
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
events = append(events, "close")
|
||||||
close(closeCh)
|
close(closeCh)
|
||||||
|
|
||||||
<-getCh
|
<-getCh
|
||||||
require.Equal(t, []string{"close", "get"}, events)
|
require.Equal(t, []string{"close", "get"}, events)
|
||||||
})
|
})
|
||||||
|
t.Run("test gc tryClose false, many parallel get", func(t *testing.T) {
|
||||||
|
timesCalled := &atomic.Int32{}
|
||||||
|
obj := NewTestObject("id", false, nil)
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
timesCalled.Add(1)
|
||||||
|
return obj, nil
|
||||||
|
}, WithTTL(0))
|
||||||
|
|
||||||
|
val, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
assert.Equal(t, 1, c.Len())
|
||||||
|
begin := make(chan struct{})
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
once := sync.Once{}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
<-begin
|
||||||
|
c.GC()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(i int) {
|
||||||
|
once.Do(func() {
|
||||||
|
close(begin)
|
||||||
|
})
|
||||||
|
if i%2 != 0 {
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
_, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
wg.Wait()
|
||||||
|
require.Equal(t, timesCalled.Load(), int32(1))
|
||||||
|
require.True(t, obj.tryCloseCalled)
|
||||||
|
})
|
||||||
|
t.Run("test gc tryClose different, many objects", func(t *testing.T) {
|
||||||
|
tryCloseIds := make(map[string]bool)
|
||||||
|
called := make(map[string]int)
|
||||||
|
max := 1000
|
||||||
|
getId := func(i int) string {
|
||||||
|
return fmt.Sprintf("id%d", i)
|
||||||
|
}
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
if i%2 == 1 {
|
||||||
|
tryCloseIds[getId(i)] = true
|
||||||
|
} else {
|
||||||
|
tryCloseIds[getId(i)] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
called[id] = called[id] + 1
|
||||||
|
return NewTestObject(id, tryCloseIds[id], nil), nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
val, err := c.Get(context.TODO(), getId(i))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
}
|
||||||
|
assert.Equal(t, max, c.Len())
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
c.GC()
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
val, err := c.Get(context.TODO(), getId(i))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
}
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
val, err := c.Get(context.TODO(), getId(i))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
require.Equal(t, called[getId(i)], i%2+1)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_OCache_Remove(t *testing.T) {
|
func Test_OCache_Remove(t *testing.T) {
|
||||||
closeCh := make(chan struct{})
|
t.Run("remove simple", func(t *testing.T) {
|
||||||
getCh := make(chan struct{})
|
closeCh := make(chan struct{})
|
||||||
|
getCh := make(chan struct{})
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, false, closeCh), nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
|
||||||
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
val, err := c.Get(context.TODO(), "id")
|
||||||
return NewTestObject(id, closeCh), nil
|
|
||||||
}, WithTTL(time.Millisecond*10))
|
|
||||||
val, err := c.Get(context.TODO(), "id")
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, val)
|
|
||||||
assert.Equal(t, 1, c.Len())
|
|
||||||
// removing the object, so we will wait on closing
|
|
||||||
go func() {
|
|
||||||
_, err := c.Remove("id")
|
|
||||||
require.NoError(t, err)
|
|
||||||
}()
|
|
||||||
time.Sleep(time.Millisecond * 40)
|
|
||||||
|
|
||||||
var events []string
|
|
||||||
go func() {
|
|
||||||
_, err := c.Get(context.TODO(), "id")
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, val)
|
require.NotNil(t, val)
|
||||||
events = append(events, "get")
|
assert.Equal(t, 1, c.Len())
|
||||||
close(getCh)
|
// removing the object, so we will wait on closing
|
||||||
}()
|
go func() {
|
||||||
events = append(events, "close")
|
_, err := c.Remove(ctx, "id")
|
||||||
// sleeping to make sure that Get is called
|
require.NoError(t, err)
|
||||||
time.Sleep(time.Millisecond * 40)
|
}()
|
||||||
close(closeCh)
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
|
||||||
<-getCh
|
var events []string
|
||||||
require.Equal(t, []string{"close", "get"}, events)
|
go func() {
|
||||||
|
_, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
events = append(events, "get")
|
||||||
|
close(getCh)
|
||||||
|
}()
|
||||||
|
// sleeping to make sure that Get is called
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
events = append(events, "close")
|
||||||
|
close(closeCh)
|
||||||
|
|
||||||
|
<-getCh
|
||||||
|
require.Equal(t, []string{"close", "get"}, events)
|
||||||
|
})
|
||||||
|
t.Run("test remove while gc, tryClose false", func(t *testing.T) {
|
||||||
|
closeCh := make(chan struct{})
|
||||||
|
removeCh := make(chan struct{})
|
||||||
|
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, false, closeCh), nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
val, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
assert.Equal(t, 1, c.Len())
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
go c.GC()
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
var events []string
|
||||||
|
go func() {
|
||||||
|
ok, err := c.Remove(ctx, "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, ok)
|
||||||
|
events = append(events, "remove")
|
||||||
|
close(removeCh)
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
events = append(events, "close")
|
||||||
|
close(closeCh)
|
||||||
|
|
||||||
|
<-removeCh
|
||||||
|
require.Equal(t, []string{"close", "remove"}, events)
|
||||||
|
})
|
||||||
|
t.Run("test remove while gc, tryClose true", func(t *testing.T) {
|
||||||
|
closeCh := make(chan struct{})
|
||||||
|
removeCh := make(chan struct{})
|
||||||
|
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, true, closeCh), nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
val, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
assert.Equal(t, 1, c.Len())
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
go c.GC()
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
var events []string
|
||||||
|
go func() {
|
||||||
|
ok, err := c.Remove(ctx, "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, ok)
|
||||||
|
events = append(events, "remove")
|
||||||
|
close(removeCh)
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Millisecond * 20)
|
||||||
|
events = append(events, "close")
|
||||||
|
close(closeCh)
|
||||||
|
|
||||||
|
<-removeCh
|
||||||
|
require.Equal(t, []string{"close", "remove"}, events)
|
||||||
|
})
|
||||||
|
t.Run("test gc while remove, tryClose true", func(t *testing.T) {
|
||||||
|
closeCh := make(chan struct{})
|
||||||
|
removeCh := make(chan struct{})
|
||||||
|
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, true, closeCh), nil
|
||||||
|
}, WithTTL(time.Millisecond*10))
|
||||||
|
val, err := c.Get(context.TODO(), "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
assert.Equal(t, 1, c.Len())
|
||||||
|
go func() {
|
||||||
|
ok, err := c.Remove(ctx, "id")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, ok)
|
||||||
|
close(removeCh)
|
||||||
|
}()
|
||||||
|
time.Sleep(20 * time.Millisecond)
|
||||||
|
c.GC()
|
||||||
|
close(closeCh)
|
||||||
|
<-removeCh
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOCacheFuzzy(t *testing.T) {
|
||||||
|
t.Run("test many objects gc, get and remove simultaneously, close after", func(t *testing.T) {
|
||||||
|
tryCloseIds := make(map[string]bool)
|
||||||
|
max := 2000
|
||||||
|
getId := func(i int) string {
|
||||||
|
return fmt.Sprintf("id%d", i)
|
||||||
|
}
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
if i%2 == 1 {
|
||||||
|
tryCloseIds[getId(i)] = true
|
||||||
|
} else {
|
||||||
|
tryCloseIds[getId(i)] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, tryCloseIds[id], nil), nil
|
||||||
|
}, WithTTL(time.Nanosecond))
|
||||||
|
|
||||||
|
stopGC := make(chan struct{})
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-stopGC:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
c.GC()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
val, err := c.Get(context.TODO(), getId(i))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
c.Remove(ctx, getId(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
wg.Wait()
|
||||||
|
close(stopGC)
|
||||||
|
err := c.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, c.Len())
|
||||||
|
})
|
||||||
|
t.Run("test many objects gc, get, remove and close simultaneously", func(t *testing.T) {
|
||||||
|
tryCloseIds := make(map[string]bool)
|
||||||
|
max := 2000
|
||||||
|
getId := func(i int) string {
|
||||||
|
return fmt.Sprintf("id%d", i)
|
||||||
|
}
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
if i%2 == 1 {
|
||||||
|
tryCloseIds[getId(i)] = true
|
||||||
|
} else {
|
||||||
|
tryCloseIds[getId(i)] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := New(func(ctx context.Context, id string) (value Object, err error) {
|
||||||
|
return NewTestObject(id, tryCloseIds[id], nil), nil
|
||||||
|
}, WithTTL(time.Nanosecond))
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
c.GC()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
val, err := c.Get(context.TODO(), getId(i))
|
||||||
|
if err == ErrClosed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
for i := 0; i < max; i++ {
|
||||||
|
c.Remove(ctx, getId(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
err := c.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, c.Len())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,10 @@ func (p pushSpaceRequestMatcher) String() string {
|
|||||||
|
|
||||||
type mockPeer struct{}
|
type mockPeer struct{}
|
||||||
|
|
||||||
|
func (m mockPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||||
|
return true, m.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (m mockPeer) Id() string {
|
func (m mockPeer) Id() string {
|
||||||
return "mockId"
|
return "mockId"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,7 +88,7 @@ func (a *aclRecordBuilder) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyByt
|
|||||||
Identity: state.Identity(),
|
Identity: state.Identity(),
|
||||||
Data: marshalledJoin,
|
Data: marshalledJoin,
|
||||||
CurrentReadKeyHash: state.CurrentReadKeyHash(),
|
CurrentReadKeyHash: state.CurrentReadKeyHash(),
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
marshalledRecord, err := aclRecord.Marshal()
|
marshalledRecord, err := aclRecord.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -126,7 +126,7 @@ func (t *AclListStorageBuilder) parseRecord(rec *Record, prevId string) *aclreco
|
|||||||
Identity: []byte(t.keychain.GetIdentity(rec.Identity)),
|
Identity: []byte(t.keychain.GetIdentity(rec.Identity)),
|
||||||
Data: bytes,
|
Data: bytes,
|
||||||
CurrentReadKeyHash: k.Hash,
|
CurrentReadKeyHash: k.Hash,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package objecttree
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
"github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -48,6 +49,11 @@ func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
|
func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
|
||||||
|
changeInfo := &treechangeproto.TreeChangeInfo{
|
||||||
|
ChangeType: ch.ChangeType,
|
||||||
|
ChangePayload: ch.ChangePayload,
|
||||||
|
}
|
||||||
|
data, _ := proto.Marshal(changeInfo)
|
||||||
return &Change{
|
return &Change{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
AclHeadId: ch.AclHeadId,
|
AclHeadId: ch.AclHeadId,
|
||||||
@ -56,7 +62,8 @@ func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []by
|
|||||||
Timestamp: ch.Timestamp,
|
Timestamp: ch.Timestamp,
|
||||||
Identity: string(ch.Identity),
|
Identity: string(ch.Identity),
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
Data: []byte(ch.ChangeType),
|
Data: data,
|
||||||
|
Model: changeInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,13 +26,14 @@ type BuilderContent struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InitialContent struct {
|
type InitialContent struct {
|
||||||
AclHeadId string
|
AclHeadId string
|
||||||
Identity []byte
|
Identity []byte
|
||||||
SigningKey signingkey.PrivKey
|
SigningKey signingkey.PrivKey
|
||||||
SpaceId string
|
SpaceId string
|
||||||
Seed []byte
|
Seed []byte
|
||||||
ChangeType string
|
ChangeType string
|
||||||
Timestamp int64
|
ChangePayload []byte
|
||||||
|
Timestamp int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type nonVerifiableChangeBuilder struct {
|
type nonVerifiableChangeBuilder struct {
|
||||||
@ -122,41 +123,35 @@ func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeCha
|
|||||||
|
|
||||||
func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
|
func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
change := &treechangeproto.RootChange{
|
change := &treechangeproto.RootChange{
|
||||||
AclHeadId: payload.AclHeadId,
|
AclHeadId: payload.AclHeadId,
|
||||||
Timestamp: payload.Timestamp,
|
Timestamp: payload.Timestamp,
|
||||||
Identity: payload.Identity,
|
Identity: payload.Identity,
|
||||||
ChangeType: payload.ChangeType,
|
ChangeType: payload.ChangeType,
|
||||||
SpaceId: payload.SpaceId,
|
ChangePayload: payload.ChangePayload,
|
||||||
Seed: payload.Seed,
|
SpaceId: payload.SpaceId,
|
||||||
|
Seed: payload.Seed,
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalledChange, err := proto.Marshal(change)
|
marshalledChange, err := proto.Marshal(change)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := payload.SigningKey.Sign(marshalledChange)
|
signature, err := payload.SigningKey.Sign(marshalledChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := &treechangeproto.RawTreeChange{
|
raw := &treechangeproto.RawTreeChange{
|
||||||
Payload: marshalledChange,
|
Payload: marshalledChange,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalledRawChange, err := proto.Marshal(raw)
|
marshalledRawChange, err := proto.Marshal(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
|
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChangeFromRoot(id, change, signature)
|
ch = NewChangeFromRoot(id, change, signature)
|
||||||
|
|
||||||
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
||||||
RawChange: marshalledRawChange,
|
RawChange: marshalledRawChange,
|
||||||
Id: id,
|
Id: id,
|
||||||
@ -170,7 +165,7 @@ func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *
|
|||||||
AclHeadId: payload.AclHeadId,
|
AclHeadId: payload.AclHeadId,
|
||||||
SnapshotBaseId: payload.SnapshotBaseId,
|
SnapshotBaseId: payload.SnapshotBaseId,
|
||||||
CurrentReadKeyHash: payload.CurrentReadKeyHash,
|
CurrentReadKeyHash: payload.CurrentReadKeyHash,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
Identity: payload.Identity,
|
Identity: payload.Identity,
|
||||||
IsSnapshot: payload.IsSnapshot,
|
IsSnapshot: payload.IsSnapshot,
|
||||||
}
|
}
|
||||||
@ -184,34 +179,27 @@ func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *
|
|||||||
} else {
|
} else {
|
||||||
change.ChangesData = payload.Content
|
change.ChangesData = payload.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalledChange, err := proto.Marshal(change)
|
marshalledChange, err := proto.Marshal(change)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := payload.SigningKey.Sign(marshalledChange)
|
signature, err := payload.SigningKey.Sign(marshalledChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := &treechangeproto.RawTreeChange{
|
raw := &treechangeproto.RawTreeChange{
|
||||||
Payload: marshalledChange,
|
Payload: marshalledChange,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalledRawChange, err := proto.Marshal(raw)
|
marshalledRawChange, err := proto.Marshal(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
|
id, err := cidutil.NewCidFromBytes(marshalledRawChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChange(id, change, signature)
|
ch = NewChange(id, change, signature)
|
||||||
|
|
||||||
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
||||||
RawChange: marshalledRawChange,
|
RawChange: marshalledRawChange,
|
||||||
Id: id,
|
Id: id,
|
||||||
@ -264,7 +252,6 @@ func (c *changeBuilder) unmarshallRawChange(raw *treechangeproto.RawTreeChange,
|
|||||||
ch = NewChangeFromRoot(id, unmarshalled, raw.Signature)
|
ch = NewChangeFromRoot(id, unmarshalled, raw.Signature)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
unmarshalled := &treechangeproto.TreeChange{}
|
unmarshalled := &treechangeproto.TreeChange{}
|
||||||
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ package mock_objecttree
|
|||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
time "time"
|
||||||
|
|
||||||
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
||||||
@ -82,6 +83,20 @@ func (mr *MockObjectTreeMockRecorder) AddRawChanges(arg0, arg1 interface{}) *gom
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockObjectTree)(nil).AddRawChanges), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockObjectTree)(nil).AddRawChanges), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChangeInfo mocks base method.
|
||||||
|
func (m *MockObjectTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChangeInfo")
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeChangeInfo)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeInfo indicates an expected call of ChangeInfo.
|
||||||
|
func (mr *MockObjectTreeMockRecorder) ChangeInfo() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeInfo", reflect.TypeOf((*MockObjectTree)(nil).ChangeInfo))
|
||||||
|
}
|
||||||
|
|
||||||
// ChangesAfterCommonSnapshot mocks base method.
|
// ChangesAfterCommonSnapshot mocks base method.
|
||||||
func (m *MockObjectTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
func (m *MockObjectTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -336,6 +351,21 @@ func (mr *MockObjectTreeMockRecorder) Storage() *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockObjectTree)(nil).Storage))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Storage", reflect.TypeOf((*MockObjectTree)(nil).Storage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryClose mocks base method.
|
||||||
|
func (m *MockObjectTree) TryClose(arg0 time.Duration) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "TryClose", arg0)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryClose indicates an expected call of TryClose.
|
||||||
|
func (mr *MockObjectTreeMockRecorder) TryClose(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryClose", reflect.TypeOf((*MockObjectTree)(nil).TryClose), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// TryLock mocks base method.
|
// TryLock mocks base method.
|
||||||
func (m *MockObjectTree) TryLock() bool {
|
func (m *MockObjectTree) TryLock() bool {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
@ -52,6 +53,7 @@ type ReadableObjectTree interface {
|
|||||||
Id() string
|
Id() string
|
||||||
Header() *treechangeproto.RawTreeChangeWithId
|
Header() *treechangeproto.RawTreeChangeWithId
|
||||||
UnmarshalledHeader() *Change
|
UnmarshalledHeader() *Change
|
||||||
|
ChangeInfo() *treechangeproto.TreeChangeInfo
|
||||||
Heads() []string
|
Heads() []string
|
||||||
Root() *Change
|
Root() *Change
|
||||||
|
|
||||||
@ -81,6 +83,7 @@ type ObjectTree interface {
|
|||||||
|
|
||||||
Delete() error
|
Delete() error
|
||||||
Close() error
|
Close() error
|
||||||
|
TryClose(objectTTL time.Duration) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type objectTree struct {
|
type objectTree struct {
|
||||||
@ -142,6 +145,10 @@ func (ot *objectTree) UnmarshalledHeader() *Change {
|
|||||||
return ot.root
|
return ot.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ot *objectTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
|
||||||
|
return ot.root.Model.(*treechangeproto.TreeChangeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
func (ot *objectTree) Storage() treestorage.TreeStorage {
|
func (ot *objectTree) Storage() treestorage.TreeStorage {
|
||||||
return ot.treeStorage
|
return ot.treeStorage
|
||||||
}
|
}
|
||||||
@ -555,6 +562,10 @@ func (ot *objectTree) Root() *Change {
|
|||||||
return ot.tree.Root()
|
return ot.tree.Root()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ot *objectTree) TryClose(objectTTL time.Duration) (bool, error) {
|
||||||
|
return true, ot.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (ot *objectTree) Close() error {
|
func (ot *objectTree) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,11 +12,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ObjectTreeCreatePayload struct {
|
type ObjectTreeCreatePayload struct {
|
||||||
SignKey signingkey.PrivKey
|
SignKey signingkey.PrivKey
|
||||||
ChangeType string
|
ChangeType string
|
||||||
SpaceId string
|
ChangePayload []byte
|
||||||
Identity []byte
|
SpaceId string
|
||||||
IsEncrypted bool
|
Identity []byte
|
||||||
|
IsEncrypted bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type HistoryTreeParams struct {
|
type HistoryTreeParams struct {
|
||||||
@ -75,7 +76,7 @@ func CreateObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return createObjectTreeRoot(payload, time.Now().UnixNano(), bytes, aclList)
|
return createObjectTreeRoot(payload, time.Now().Unix(), bytes, aclList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeriveObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) {
|
func DeriveObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
@ -125,7 +126,7 @@ func CreateObjectTree(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return createObjectTree(payload, time.Now().UnixNano(), bytes, aclList, createStorage)
|
return createObjectTree(payload, time.Now().Unix(), bytes, aclList, createStorage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createObjectTree(
|
func createObjectTree(
|
||||||
@ -165,13 +166,14 @@ func createObjectTreeRoot(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cnt := InitialContent{
|
cnt := InitialContent{
|
||||||
AclHeadId: aclHeadId,
|
AclHeadId: aclHeadId,
|
||||||
Identity: payload.Identity,
|
Identity: payload.Identity,
|
||||||
SigningKey: payload.SignKey,
|
SigningKey: payload.SignKey,
|
||||||
SpaceId: payload.SpaceId,
|
SpaceId: payload.SpaceId,
|
||||||
ChangeType: payload.ChangeType,
|
ChangeType: payload.ChangeType,
|
||||||
Timestamp: timestamp,
|
ChangePayload: payload.ChangePayload,
|
||||||
Seed: seed,
|
Timestamp: timestamp,
|
||||||
|
Seed: seed,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt)
|
_, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt)
|
||||||
|
|||||||
@ -125,7 +125,7 @@ func TestTree_Hash(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTree_AddFuzzy(t *testing.T) {
|
func TestTree_AddFuzzy(t *testing.T) {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().Unix())
|
||||||
getChanges := func() []*Change {
|
getChanges := func() []*Change {
|
||||||
changes := []*Change{
|
changes := []*Change{
|
||||||
newChange("1", "root", "root"),
|
newChange("1", "root", "root"),
|
||||||
|
|||||||
@ -7,6 +7,7 @@ package mock_synctree
|
|||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
time "time"
|
||||||
|
|
||||||
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
|
||||||
@ -193,6 +194,20 @@ func (mr *MockSyncTreeMockRecorder) AddRawChanges(arg0, arg1 interface{}) *gomoc
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockSyncTree)(nil).AddRawChanges), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRawChanges", reflect.TypeOf((*MockSyncTree)(nil).AddRawChanges), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChangeInfo mocks base method.
|
||||||
|
func (m *MockSyncTree) ChangeInfo() *treechangeproto.TreeChangeInfo {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ChangeInfo")
|
||||||
|
ret0, _ := ret[0].(*treechangeproto.TreeChangeInfo)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeInfo indicates an expected call of ChangeInfo.
|
||||||
|
func (mr *MockSyncTreeMockRecorder) ChangeInfo() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeInfo", reflect.TypeOf((*MockSyncTree)(nil).ChangeInfo))
|
||||||
|
}
|
||||||
|
|
||||||
// ChangesAfterCommonSnapshot mocks base method.
|
// ChangesAfterCommonSnapshot mocks base method.
|
||||||
func (m *MockSyncTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
func (m *MockSyncTree) ChangesAfterCommonSnapshot(arg0, arg1 []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -487,6 +502,21 @@ func (mr *MockSyncTreeMockRecorder) SyncWithPeer(arg0, arg1 interface{}) *gomock
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncWithPeer", reflect.TypeOf((*MockSyncTree)(nil).SyncWithPeer), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SyncWithPeer", reflect.TypeOf((*MockSyncTree)(nil).SyncWithPeer), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryClose mocks base method.
|
||||||
|
func (m *MockSyncTree) TryClose(arg0 time.Duration) (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "TryClose", arg0)
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// TryClose indicates an expected call of TryClose.
|
||||||
|
func (mr *MockSyncTreeMockRecorder) TryClose(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TryClose", reflect.TypeOf((*MockSyncTree)(nil).TryClose), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
// TryLock mocks base method.
|
// TryLock mocks base method.
|
||||||
func (m *MockSyncTree) TryLock() bool {
|
func (m *MockSyncTree) TryLock() bool {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package synctree
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/anytypeio/any-sync/app/logger"
|
"github.com/anytypeio/any-sync/app/logger"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
@ -209,6 +210,10 @@ func (s *syncTree) Delete() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *syncTree) TryClose(objectTTL time.Duration) (bool, error) {
|
||||||
|
return true, s.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *syncTree) Close() (err error) {
|
func (s *syncTree) Close() (err error) {
|
||||||
log.Debug("closing sync tree", zap.String("id", s.Id()))
|
log.Debug("closing sync tree", zap.String("id", s.Id()))
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@ -16,6 +16,8 @@ message RootChange {
|
|||||||
bytes seed = 5;
|
bytes seed = 5;
|
||||||
// Identity is a public key of the tree's creator
|
// Identity is a public key of the tree's creator
|
||||||
bytes identity = 6;
|
bytes identity = 6;
|
||||||
|
// ChangePayload is a payload related to ChangeType
|
||||||
|
bytes changePayload = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeChange is a change of a tree
|
// TreeChange is a change of a tree
|
||||||
@ -94,3 +96,9 @@ message TreeFullSyncResponse {
|
|||||||
message TreeErrorResponse {
|
message TreeErrorResponse {
|
||||||
string error = 1;
|
string error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeChangeInfo is used internally in Tree implementation for ease of marshalling
|
||||||
|
message TreeChangeInfo {
|
||||||
|
string changeType = 1;
|
||||||
|
bytes changePayload = 2;
|
||||||
|
}
|
||||||
|
|||||||
@ -36,6 +36,8 @@ type RootChange struct {
|
|||||||
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
|
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
|
||||||
// Identity is a public key of the tree's creator
|
// Identity is a public key of the tree's creator
|
||||||
Identity []byte `protobuf:"bytes,6,opt,name=identity,proto3" json:"identity,omitempty"`
|
Identity []byte `protobuf:"bytes,6,opt,name=identity,proto3" json:"identity,omitempty"`
|
||||||
|
// ChangePayload is a payload related to ChangeType
|
||||||
|
ChangePayload []byte `protobuf:"bytes,7,opt,name=changePayload,proto3" json:"changePayload,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RootChange) Reset() { *m = RootChange{} }
|
func (m *RootChange) Reset() { *m = RootChange{} }
|
||||||
@ -113,6 +115,13 @@ func (m *RootChange) GetIdentity() []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *RootChange) GetChangePayload() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.ChangePayload
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// TreeChange is a change of a tree
|
// TreeChange is a change of a tree
|
||||||
type TreeChange struct {
|
type TreeChange struct {
|
||||||
// TreeHeadIds are previous ids for this TreeChange
|
// TreeHeadIds are previous ids for this TreeChange
|
||||||
@ -725,6 +734,59 @@ func (m *TreeErrorResponse) GetError() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TreeChangeInfo is used internally in Tree implementation for ease of marshalling
|
||||||
|
type TreeChangeInfo struct {
|
||||||
|
ChangeType string `protobuf:"bytes,1,opt,name=changeType,proto3" json:"changeType,omitempty"`
|
||||||
|
ChangePayload []byte `protobuf:"bytes,2,opt,name=changePayload,proto3" json:"changePayload,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) Reset() { *m = TreeChangeInfo{} }
|
||||||
|
func (m *TreeChangeInfo) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*TreeChangeInfo) ProtoMessage() {}
|
||||||
|
func (*TreeChangeInfo) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_5033f0301ef9b772, []int{10}
|
||||||
|
}
|
||||||
|
func (m *TreeChangeInfo) XXX_Unmarshal(b []byte) error {
|
||||||
|
return m.Unmarshal(b)
|
||||||
|
}
|
||||||
|
func (m *TreeChangeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
if deterministic {
|
||||||
|
return xxx_messageInfo_TreeChangeInfo.Marshal(b, m, deterministic)
|
||||||
|
} else {
|
||||||
|
b = b[:cap(b)]
|
||||||
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b[:n], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (m *TreeChangeInfo) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_TreeChangeInfo.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *TreeChangeInfo) XXX_Size() int {
|
||||||
|
return m.Size()
|
||||||
|
}
|
||||||
|
func (m *TreeChangeInfo) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_TreeChangeInfo.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_TreeChangeInfo proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) GetChangeType() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.ChangeType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) GetChangePayload() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.ChangePayload
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*RootChange)(nil), "treechange.RootChange")
|
proto.RegisterType((*RootChange)(nil), "treechange.RootChange")
|
||||||
proto.RegisterType((*TreeChange)(nil), "treechange.TreeChange")
|
proto.RegisterType((*TreeChange)(nil), "treechange.TreeChange")
|
||||||
@ -736,6 +798,7 @@ func init() {
|
|||||||
proto.RegisterType((*TreeFullSyncRequest)(nil), "treechange.TreeFullSyncRequest")
|
proto.RegisterType((*TreeFullSyncRequest)(nil), "treechange.TreeFullSyncRequest")
|
||||||
proto.RegisterType((*TreeFullSyncResponse)(nil), "treechange.TreeFullSyncResponse")
|
proto.RegisterType((*TreeFullSyncResponse)(nil), "treechange.TreeFullSyncResponse")
|
||||||
proto.RegisterType((*TreeErrorResponse)(nil), "treechange.TreeErrorResponse")
|
proto.RegisterType((*TreeErrorResponse)(nil), "treechange.TreeErrorResponse")
|
||||||
|
proto.RegisterType((*TreeChangeInfo)(nil), "treechange.TreeChangeInfo")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -743,48 +806,51 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_5033f0301ef9b772 = []byte{
|
var fileDescriptor_5033f0301ef9b772 = []byte{
|
||||||
// 656 bytes of a gzipped FileDescriptorProto
|
// 690 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xc1, 0x6e, 0xd3, 0x40,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xc1, 0x4e, 0xdb, 0x4a,
|
||||||
0x10, 0xf5, 0x3a, 0x69, 0xd3, 0x4e, 0xd3, 0x16, 0xb6, 0x3d, 0x58, 0x15, 0x18, 0xcb, 0x07, 0x08,
|
0x14, 0xf5, 0x38, 0x01, 0xc3, 0x25, 0xc0, 0x7b, 0x03, 0x0b, 0x0b, 0xbd, 0xe7, 0x5a, 0x56, 0xd5,
|
||||||
0x97, 0x56, 0x2a, 0x27, 0x10, 0x52, 0x45, 0x4b, 0x8b, 0xab, 0x0a, 0x84, 0xb6, 0x05, 0x24, 0x6e,
|
0xa6, 0x1b, 0x90, 0xe8, 0xaa, 0x55, 0x25, 0x54, 0x28, 0xd4, 0x11, 0x6a, 0x85, 0x06, 0x4a, 0xa5,
|
||||||
0x5b, 0x7b, 0x68, 0x8c, 0x12, 0xdb, 0x78, 0x37, 0x54, 0xf9, 0x00, 0x2e, 0x20, 0x21, 0x3e, 0x81,
|
0xee, 0x06, 0xfb, 0x42, 0x5c, 0x25, 0xb6, 0xeb, 0x99, 0x14, 0xe5, 0x03, 0xba, 0x69, 0xa5, 0xaa,
|
||||||
0x6f, 0xe0, 0x0f, 0xb8, 0x71, 0xec, 0x91, 0x23, 0x6a, 0x7e, 0x04, 0xed, 0x3a, 0x4e, 0xd6, 0x6e,
|
0x9f, 0xd0, 0x5f, 0xe9, 0xae, 0x4b, 0x96, 0x2c, 0x2b, 0xf8, 0x91, 0xca, 0x63, 0x3b, 0xb1, 0x1d,
|
||||||
0x0e, 0xbd, 0xf5, 0xb2, 0xc9, 0xbc, 0x9d, 0x79, 0xfb, 0xe6, 0xcd, 0x6e, 0x02, 0x3b, 0x61, 0xda,
|
0x2f, 0xd8, 0xb1, 0x71, 0x72, 0x8f, 0xef, 0x3d, 0x73, 0xee, 0xb9, 0x33, 0x63, 0xd8, 0xf1, 0xa2,
|
||||||
0xef, 0xa7, 0x89, 0xc8, 0x78, 0x88, 0x5b, 0xe9, 0xe9, 0x47, 0x0c, 0xe5, 0x96, 0xcc, 0x11, 0xf5,
|
0xe1, 0x30, 0x0a, 0x45, 0xcc, 0x3d, 0xdc, 0x8a, 0xce, 0x3e, 0xa2, 0x27, 0xb7, 0x64, 0x82, 0xa8,
|
||||||
0x12, 0x76, 0x79, 0x72, 0x86, 0x59, 0x9e, 0xca, 0x74, 0x4b, 0xaf, 0xc2, 0x80, 0x37, 0x35, 0x42,
|
0x1e, 0x5e, 0x9f, 0x87, 0x17, 0x18, 0x27, 0x91, 0x8c, 0xb6, 0xd4, 0x53, 0x94, 0xe0, 0x4d, 0x85,
|
||||||
0x61, 0x8a, 0xf8, 0xbf, 0x08, 0x00, 0x4b, 0x53, 0xb9, 0xa7, 0x43, 0x7a, 0x07, 0x16, 0x79, 0xd8,
|
0x50, 0x98, 0x22, 0xce, 0x35, 0x01, 0x60, 0x51, 0x24, 0xf7, 0x54, 0x48, 0xff, 0x83, 0x45, 0xee,
|
||||||
0x0b, 0x90, 0x47, 0x87, 0x91, 0x43, 0x3c, 0xd2, 0x59, 0x64, 0x53, 0x80, 0x3a, 0xd0, 0xd2, 0xa7,
|
0x0d, 0x5c, 0xe4, 0x7e, 0xcf, 0x37, 0x89, 0x4d, 0xba, 0x8b, 0x6c, 0x0a, 0x50, 0x13, 0x0c, 0xb5,
|
||||||
0x1e, 0x46, 0x8e, 0xad, 0xf7, 0xca, 0x90, 0xba, 0x00, 0x05, 0xe1, 0xc9, 0x30, 0x43, 0xa7, 0xa1,
|
0x6a, 0xcf, 0x37, 0x75, 0xf5, 0xae, 0x08, 0xa9, 0x05, 0x90, 0x11, 0x9e, 0x8c, 0x63, 0x34, 0x5b,
|
||||||
0x37, 0x0d, 0x44, 0xf1, 0xca, 0xb8, 0x8f, 0x42, 0xf2, 0x7e, 0xe6, 0x34, 0x3d, 0xd2, 0x69, 0xb0,
|
0xea, 0x65, 0x09, 0x49, 0x79, 0x65, 0x30, 0x44, 0x21, 0xf9, 0x30, 0x36, 0xdb, 0x36, 0xe9, 0xb6,
|
||||||
0x29, 0x40, 0x29, 0x34, 0x05, 0x62, 0xe4, 0xcc, 0x79, 0xa4, 0xd3, 0x66, 0xfa, 0x3b, 0xdd, 0x80,
|
0xd8, 0x14, 0xa0, 0x14, 0xda, 0x02, 0xd1, 0x37, 0xe7, 0x6c, 0xd2, 0xed, 0x30, 0xf5, 0x9f, 0x6e,
|
||||||
0x85, 0x38, 0xc2, 0x44, 0xc6, 0x72, 0xe8, 0xcc, 0x6b, 0x7c, 0x12, 0xfb, 0x3f, 0x6d, 0x80, 0x93,
|
0xc0, 0x42, 0xe0, 0x63, 0x28, 0x03, 0x39, 0x36, 0xe7, 0x15, 0x3e, 0x89, 0xe9, 0x43, 0x58, 0xce,
|
||||||
0x1c, 0x71, 0x2c, 0xda, 0x83, 0x25, 0xd5, 0x51, 0x21, 0x52, 0x38, 0xc4, 0x6b, 0x74, 0x16, 0x99,
|
0xb8, 0x8f, 0xf8, 0x78, 0x10, 0x71, 0xdf, 0x34, 0x54, 0x42, 0x15, 0x74, 0x7e, 0xea, 0x00, 0x27,
|
||||||
0x09, 0x55, 0xdb, 0xb2, 0xeb, 0x6d, 0xdd, 0x87, 0x15, 0x91, 0xf0, 0x4c, 0x74, 0x53, 0xb9, 0xcb,
|
0x09, 0x62, 0xde, 0x9a, 0x0d, 0x4b, 0x69, 0xdf, 0x59, 0x2b, 0xc2, 0x24, 0x76, 0xab, 0xbb, 0xc8,
|
||||||
0x85, 0xea, 0xae, 0x68, 0xa0, 0x86, 0xaa, 0x73, 0x8a, 0x96, 0xc4, 0x73, 0x2e, 0xb9, 0x6e, 0xa3,
|
0xca, 0x50, 0xb5, 0x79, 0xbd, 0xde, 0xfc, 0x23, 0x58, 0x11, 0x21, 0x8f, 0x45, 0x3f, 0x92, 0xbb,
|
||||||
0xcd, 0x4c, 0x88, 0x6e, 0x02, 0x0d, 0x07, 0x79, 0x8e, 0x89, 0x64, 0xc8, 0xa3, 0x23, 0x1c, 0x06,
|
0x5c, 0xa4, 0x1e, 0x64, 0x6d, 0xd6, 0xd0, 0x74, 0x9d, 0x4c, 0x87, 0x78, 0xc5, 0x25, 0x57, 0xcd,
|
||||||
0x5c, 0x74, 0x75, 0x5b, 0x4d, 0x36, 0x63, 0xa7, 0x6a, 0xcb, 0x7c, 0xdd, 0x16, 0xd3, 0x82, 0x56,
|
0x76, 0x58, 0x19, 0xa2, 0x9b, 0x40, 0xbd, 0x51, 0x92, 0x60, 0x28, 0x19, 0x72, 0xff, 0x10, 0xc7,
|
||||||
0xd5, 0x02, 0x65, 0x78, 0x2c, 0x8e, 0xc7, 0xfa, 0x9c, 0x05, 0x8f, 0x74, 0x16, 0x98, 0x81, 0xf8,
|
0x2e, 0x17, 0x7d, 0xd5, 0x7c, 0x9b, 0x35, 0xbc, 0xa9, 0x9a, 0x37, 0x5f, 0x37, 0xaf, 0x6c, 0x94,
|
||||||
0x2f, 0x60, 0x99, 0xf1, 0x73, 0xc3, 0x24, 0x07, 0x5a, 0x19, 0x1f, 0xf6, 0x52, 0x5e, 0xcc, 0xb5,
|
0x51, 0x33, 0xca, 0x02, 0x08, 0xc4, 0x71, 0xae, 0xcf, 0x5c, 0xb0, 0x49, 0x77, 0x81, 0x95, 0x10,
|
||||||
0xcd, 0xca, 0x50, 0x89, 0x10, 0xf1, 0x59, 0xc2, 0xe5, 0x20, 0x47, 0x6d, 0x4e, 0x9b, 0x4d, 0x01,
|
0xe7, 0x35, 0x2c, 0x33, 0x7e, 0x59, 0x32, 0xc9, 0x04, 0x23, 0xce, 0x3d, 0x25, 0x8a, 0xab, 0x08,
|
||||||
0x7f, 0x0f, 0xd6, 0x2a, 0x44, 0xef, 0x62, 0xd9, 0x3d, 0xd4, 0x45, 0x39, 0x3f, 0x2f, 0xa0, 0x31,
|
0x53, 0x11, 0x22, 0xb8, 0x08, 0xb9, 0x1c, 0x25, 0xa8, 0xcc, 0xe9, 0xb0, 0x29, 0xe0, 0xec, 0xc1,
|
||||||
0xe1, 0x14, 0xa0, 0x2b, 0x60, 0xc7, 0xa5, 0xd1, 0x76, 0x1c, 0xf9, 0xdf, 0x09, 0xac, 0x2a, 0x8a,
|
0x5a, 0x85, 0xe8, 0x7d, 0x20, 0xfb, 0x3d, 0x55, 0x94, 0xf0, 0xcb, 0x0c, 0xca, 0x09, 0xa7, 0x00,
|
||||||
0xe3, 0x61, 0x12, 0xbe, 0x44, 0x21, 0xf8, 0x19, 0xd2, 0x27, 0xd0, 0x0a, 0xd3, 0x44, 0x62, 0x22,
|
0x5d, 0x01, 0x3d, 0x28, 0x8c, 0xd6, 0x03, 0xdf, 0xf9, 0x4e, 0x60, 0x35, 0xa5, 0x38, 0x1e, 0x87,
|
||||||
0x75, 0xfd, 0xd2, 0xb6, 0xb7, 0x69, 0xdc, 0xd4, 0x32, 0x7b, 0xaf, 0x48, 0x79, 0xcb, 0x7b, 0x03,
|
0xde, 0x1b, 0x14, 0x82, 0x5f, 0x20, 0x7d, 0x0e, 0x86, 0x17, 0x85, 0x12, 0x43, 0xa9, 0xea, 0x97,
|
||||||
0x64, 0x65, 0x01, 0xdd, 0x01, 0xc8, 0x27, 0x97, 0x56, 0x9f, 0xb3, 0xb4, 0x7d, 0xcf, 0x2c, 0x9f,
|
0xb6, 0xed, 0xcd, 0xd2, 0x7e, 0x2e, 0xb2, 0xf7, 0xb2, 0x94, 0x53, 0x3e, 0x18, 0x21, 0x2b, 0x0a,
|
||||||
0x21, 0x99, 0x19, 0x25, 0xfe, 0x6f, 0x1b, 0xd6, 0x67, 0x1d, 0x41, 0x9f, 0x02, 0x74, 0x91, 0x47,
|
0xe8, 0x0e, 0x40, 0x32, 0xd9, 0xda, 0x6a, 0x9d, 0xa5, 0xed, 0x07, 0xe5, 0xf2, 0x06, 0xc9, 0xac,
|
||||||
0x6f, 0xb2, 0x88, 0x4b, 0x1c, 0x0b, 0xdb, 0xa8, 0x0b, 0x0b, 0x26, 0x19, 0x81, 0xc5, 0x8c, 0x7c,
|
0x54, 0xe2, 0xfc, 0xd2, 0x61, 0xbd, 0x69, 0x09, 0xfa, 0x02, 0xa0, 0x8f, 0xdc, 0x7f, 0x17, 0xfb,
|
||||||
0x7a, 0x04, 0xab, 0x1f, 0x06, 0xbd, 0x9e, 0x62, 0x65, 0xf8, 0x69, 0x80, 0x42, 0xce, 0x12, 0xa7,
|
0x5c, 0x62, 0x2e, 0x6c, 0xa3, 0x2e, 0xcc, 0x9d, 0x64, 0xb8, 0x1a, 0x2b, 0xe5, 0xd3, 0x43, 0x58,
|
||||||
0x28, 0x0e, 0xaa, 0x69, 0x81, 0xc5, 0xea, 0x95, 0xf4, 0x15, 0xdc, 0x9a, 0x42, 0x22, 0x4b, 0x13,
|
0x3d, 0x1f, 0x0d, 0x06, 0x29, 0x2b, 0xc3, 0x4f, 0x23, 0x14, 0xb2, 0x49, 0x5c, 0x4a, 0x71, 0x50,
|
||||||
0x51, 0xbc, 0xac, 0x19, 0x4e, 0x1d, 0xd4, 0xf2, 0x02, 0x8b, 0x5d, 0xa9, 0xa5, 0xfb, 0xb0, 0x8c,
|
0x4d, 0x73, 0x35, 0x56, 0xaf, 0xa4, 0x6f, 0xe1, 0x9f, 0x29, 0x24, 0xe2, 0x28, 0x14, 0xd9, 0xf9,
|
||||||
0x79, 0x9e, 0xe6, 0x13, 0xb2, 0xa6, 0x26, 0xbb, 0x5b, 0x27, 0xdb, 0x37, 0x93, 0x02, 0x8b, 0x55,
|
0x6b, 0x70, 0xea, 0xa0, 0x96, 0xe7, 0x6a, 0x6c, 0xa6, 0x96, 0xee, 0xc3, 0x32, 0x26, 0x49, 0x94,
|
||||||
0xab, 0x76, 0x5b, 0x30, 0xf7, 0x59, 0x59, 0xe5, 0x7f, 0x21, 0xb0, 0x52, 0x75, 0x83, 0xae, 0xc3,
|
0x4c, 0xc8, 0xda, 0x8a, 0xec, 0xff, 0x3a, 0xd9, 0x7e, 0x39, 0xc9, 0xd5, 0x58, 0xb5, 0x6a, 0xd7,
|
||||||
0x9c, 0x72, 0xa3, 0x7c, 0x83, 0x45, 0x40, 0x1f, 0x43, 0x6b, 0xfc, 0x48, 0x1c, 0xdb, 0x6b, 0x5c,
|
0x80, 0xb9, 0xcf, 0xa9, 0x55, 0xce, 0x17, 0x02, 0x2b, 0x55, 0x37, 0xe8, 0x3a, 0xcc, 0xa5, 0x6e,
|
||||||
0x67, 0x54, 0x65, 0x3e, 0xf5, 0xa1, 0x5d, 0x3e, 0xc2, 0xd7, 0x5c, 0x76, 0x9d, 0x86, 0xe6, 0xad,
|
0x14, 0x67, 0x30, 0x0b, 0xe8, 0x33, 0x30, 0xf2, 0x43, 0x62, 0xea, 0x76, 0xeb, 0x2e, 0xa3, 0x2a,
|
||||||
0x60, 0xfe, 0x57, 0x02, 0x6b, 0x33, 0x2c, 0xbd, 0x19, 0x31, 0xdf, 0x48, 0x71, 0xb1, 0xea, 0x13,
|
0xf2, 0xa9, 0x03, 0x9d, 0xe2, 0x10, 0x1e, 0x71, 0xd9, 0x37, 0x5b, 0x8a, 0xb7, 0x82, 0x39, 0x5f,
|
||||||
0xb9, 0x19, 0x35, 0x0f, 0xe1, 0xf6, 0x95, 0x89, 0x2a, 0x25, 0x7a, 0xa2, 0xe3, 0xdf, 0xf7, 0x22,
|
0x09, 0xac, 0x35, 0x58, 0x7a, 0x3f, 0x62, 0xbe, 0x91, 0x6c, 0x63, 0xd5, 0x27, 0x72, 0x3f, 0x6a,
|
||||||
0xd8, 0x7d, 0xf6, 0xe7, 0xd2, 0x25, 0x17, 0x97, 0x2e, 0xf9, 0x77, 0xe9, 0x92, 0x1f, 0x23, 0xd7,
|
0x9e, 0xc0, 0xbf, 0x33, 0x13, 0x4d, 0x95, 0xa8, 0x89, 0xe6, 0x5f, 0x81, 0x2c, 0x70, 0x4e, 0xb3,
|
||||||
0xba, 0x18, 0xb9, 0xd6, 0xdf, 0x91, 0x6b, 0xbd, 0x7f, 0x70, 0xcd, 0xff, 0x9b, 0xd3, 0x79, 0xfd,
|
0x61, 0x66, 0x6b, 0xf5, 0xc2, 0xf3, 0xa8, 0x76, 0xf3, 0x93, 0x99, 0x9b, 0x7f, 0xe6, 0xae, 0xd6,
|
||||||
0xf1, 0xe8, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xa5, 0xe2, 0x7c, 0xa1, 0x06, 0x00, 0x00,
|
0x1b, 0xee, 0xea, 0xdd, 0x97, 0xbf, 0x6f, 0x2c, 0x72, 0x75, 0x63, 0x91, 0x3f, 0x37, 0x16, 0xf9,
|
||||||
|
0x71, 0x6b, 0x69, 0x57, 0xb7, 0x96, 0x76, 0x7d, 0x6b, 0x69, 0x1f, 0x1e, 0xdf, 0xf1, 0x6b, 0x77,
|
||||||
|
0x36, 0xaf, 0x7e, 0x9e, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x24, 0x93, 0x3b, 0x00, 0x1f, 0x07,
|
||||||
|
0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *RootChange) Marshal() (dAtA []byte, err error) {
|
func (m *RootChange) Marshal() (dAtA []byte, err error) {
|
||||||
@ -807,6 +873,13 @@ func (m *RootChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if len(m.ChangePayload) > 0 {
|
||||||
|
i -= len(m.ChangePayload)
|
||||||
|
copy(dAtA[i:], m.ChangePayload)
|
||||||
|
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangePayload)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x3a
|
||||||
|
}
|
||||||
if len(m.Identity) > 0 {
|
if len(m.Identity) > 0 {
|
||||||
i -= len(m.Identity)
|
i -= len(m.Identity)
|
||||||
copy(dAtA[i:], m.Identity)
|
copy(dAtA[i:], m.Identity)
|
||||||
@ -1362,6 +1435,43 @@ func (m *TreeErrorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) Marshal() (dAtA []byte, err error) {
|
||||||
|
size := m.Size()
|
||||||
|
dAtA = make([]byte, size)
|
||||||
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dAtA[:n], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) MarshalTo(dAtA []byte) (int, error) {
|
||||||
|
size := m.Size()
|
||||||
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
|
i := len(dAtA)
|
||||||
|
_ = i
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
if len(m.ChangePayload) > 0 {
|
||||||
|
i -= len(m.ChangePayload)
|
||||||
|
copy(dAtA[i:], m.ChangePayload)
|
||||||
|
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangePayload)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x12
|
||||||
|
}
|
||||||
|
if len(m.ChangeType) > 0 {
|
||||||
|
i -= len(m.ChangeType)
|
||||||
|
copy(dAtA[i:], m.ChangeType)
|
||||||
|
i = encodeVarintTreechange(dAtA, i, uint64(len(m.ChangeType)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0xa
|
||||||
|
}
|
||||||
|
return len(dAtA) - i, nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeVarintTreechange(dAtA []byte, offset int, v uint64) int {
|
func encodeVarintTreechange(dAtA []byte, offset int, v uint64) int {
|
||||||
offset -= sovTreechange(v)
|
offset -= sovTreechange(v)
|
||||||
base := offset
|
base := offset
|
||||||
@ -1402,6 +1512,10 @@ func (m *RootChange) Size() (n int) {
|
|||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sovTreechange(uint64(l))
|
n += 1 + l + sovTreechange(uint64(l))
|
||||||
}
|
}
|
||||||
|
l = len(m.ChangePayload)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovTreechange(uint64(l))
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1650,6 +1764,23 @@ func (m *TreeErrorResponse) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *TreeChangeInfo) Size() (n int) {
|
||||||
|
if m == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
l = len(m.ChangeType)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovTreechange(uint64(l))
|
||||||
|
}
|
||||||
|
l = len(m.ChangePayload)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovTreechange(uint64(l))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
func sovTreechange(x uint64) (n int) {
|
func sovTreechange(x uint64) (n int) {
|
||||||
return (math_bits.Len64(x|1) + 6) / 7
|
return (math_bits.Len64(x|1) + 6) / 7
|
||||||
}
|
}
|
||||||
@ -1868,6 +1999,40 @@ func (m *RootChange) Unmarshal(dAtA []byte) error {
|
|||||||
m.Identity = []byte{}
|
m.Identity = []byte{}
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
case 7:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field ChangePayload", wireType)
|
||||||
|
}
|
||||||
|
var byteLen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowTreechange
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
byteLen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if byteLen < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + byteLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.ChangePayload = append(m.ChangePayload[:0], dAtA[iNdEx:postIndex]...)
|
||||||
|
if m.ChangePayload == nil {
|
||||||
|
m.ChangePayload = []byte{}
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipTreechange(dAtA[iNdEx:])
|
skippy, err := skipTreechange(dAtA[iNdEx:])
|
||||||
@ -3233,6 +3398,122 @@ func (m *TreeErrorResponse) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (m *TreeChangeInfo) Unmarshal(dAtA []byte) error {
|
||||||
|
l := len(dAtA)
|
||||||
|
iNdEx := 0
|
||||||
|
for iNdEx < l {
|
||||||
|
preIndex := iNdEx
|
||||||
|
var wire uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowTreechange
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
wire |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldNum := int32(wire >> 3)
|
||||||
|
wireType := int(wire & 0x7)
|
||||||
|
if wireType == 4 {
|
||||||
|
return fmt.Errorf("proto: TreeChangeInfo: wiretype end group for non-group")
|
||||||
|
}
|
||||||
|
if fieldNum <= 0 {
|
||||||
|
return fmt.Errorf("proto: TreeChangeInfo: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
|
}
|
||||||
|
switch fieldNum {
|
||||||
|
case 1:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field ChangeType", wireType)
|
||||||
|
}
|
||||||
|
var stringLen uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowTreechange
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
stringLen |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intStringLen := int(stringLen)
|
||||||
|
if intStringLen < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + intStringLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.ChangeType = string(dAtA[iNdEx:postIndex])
|
||||||
|
iNdEx = postIndex
|
||||||
|
case 2:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field ChangePayload", wireType)
|
||||||
|
}
|
||||||
|
var byteLen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowTreechange
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
byteLen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if byteLen < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + byteLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.ChangePayload = append(m.ChangePayload[:0], dAtA[iNdEx:postIndex]...)
|
||||||
|
if m.ChangePayload == nil {
|
||||||
|
m.ChangePayload = []byte{}
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
|
default:
|
||||||
|
iNdEx = preIndex
|
||||||
|
skippy, err := skipTreechange(dAtA[iNdEx:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
|
return ErrInvalidLengthTreechange
|
||||||
|
}
|
||||||
|
if (iNdEx + skippy) > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
iNdEx += skippy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iNdEx > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func skipTreechange(dAtA []byte) (n int, err error) {
|
func skipTreechange(dAtA []byte) (n int, err error) {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package objectsync
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/any-sync/app/ocache"
|
|
||||||
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
|
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
|
||||||
"github.com/anytypeio/any-sync/commonspace/peermanager"
|
"github.com/anytypeio/any-sync/commonspace/peermanager"
|
||||||
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
|
"github.com/anytypeio/any-sync/commonspace/spacesyncproto"
|
||||||
@ -15,9 +14,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type LastUsage interface {
|
||||||
|
LastUsage() time.Time
|
||||||
|
}
|
||||||
|
|
||||||
// MessagePool can be made generic to work with different streams
|
// MessagePool can be made generic to work with different streams
|
||||||
type MessagePool interface {
|
type MessagePool interface {
|
||||||
ocache.ObjectLastUsage
|
LastUsage
|
||||||
synchandler.SyncHandler
|
synchandler.SyncHandler
|
||||||
peermanager.PeerManager
|
peermanager.PeerManager
|
||||||
SendSync(ctx context.Context, peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error)
|
SendSync(ctx context.Context, peerId string, message *spacesyncproto.ObjectSyncMessage) (reply *spacesyncproto.ObjectSyncMessage, err error)
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/anytypeio/any-sync/app/logger"
|
"github.com/anytypeio/any-sync/app/logger"
|
||||||
"github.com/anytypeio/any-sync/app/ocache"
|
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/syncobjectgetter"
|
"github.com/anytypeio/any-sync/commonspace/object/syncobjectgetter"
|
||||||
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
|
"github.com/anytypeio/any-sync/commonspace/objectsync/synchandler"
|
||||||
"github.com/anytypeio/any-sync/commonspace/peermanager"
|
"github.com/anytypeio/any-sync/commonspace/peermanager"
|
||||||
@ -20,7 +19,7 @@ import (
|
|||||||
var log = logger.NewNamed("common.commonspace.objectsync")
|
var log = logger.NewNamed("common.commonspace.objectsync")
|
||||||
|
|
||||||
type ObjectSync interface {
|
type ObjectSync interface {
|
||||||
ocache.ObjectLastUsage
|
LastUsage
|
||||||
synchandler.SyncHandler
|
synchandler.SyncHandler
|
||||||
MessagePool() MessagePool
|
MessagePool() MessagePool
|
||||||
|
|
||||||
|
|||||||
@ -14,8 +14,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SpaceSettingsChangeType = "reserved.spacesettings"
|
SpaceReserved = "any-sync.space"
|
||||||
SpaceDerivationScheme = "derivation.standard"
|
SpaceDerivationScheme = "derivation.standard"
|
||||||
)
|
)
|
||||||
|
|
||||||
func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) {
|
func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload spacestorage.SpaceStorageCreatePayload, err error) {
|
||||||
@ -36,11 +36,12 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
header := &spacesyncproto.SpaceHeader{
|
header := &spacesyncproto.SpaceHeader{
|
||||||
Identity: identity,
|
Identity: identity,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
SpaceType: payload.SpaceType,
|
SpaceType: payload.SpaceType,
|
||||||
ReplicationKey: payload.ReplicationKey,
|
SpaceHeaderPayload: payload.SpacePayload,
|
||||||
Seed: spaceHeaderSeed,
|
ReplicationKey: payload.ReplicationKey,
|
||||||
|
Seed: spaceHeaderSeed,
|
||||||
}
|
}
|
||||||
marshalled, err := header.Marshal()
|
marshalled, err := header.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -81,7 +82,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
|
|||||||
SpaceId: spaceId,
|
SpaceId: spaceId,
|
||||||
EncryptedReadKey: encReadKey,
|
EncryptedReadKey: encReadKey,
|
||||||
CurrentReadKeyHash: readKeyHash,
|
CurrentReadKeyHash: readKeyHash,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
rawWithId, err := marshalAclRoot(aclRoot, payload.SigningKey)
|
rawWithId, err := marshalAclRoot(aclRoot, payload.SigningKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -101,8 +102,8 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
|
|||||||
SigningKey: payload.SigningKey,
|
SigningKey: payload.SigningKey,
|
||||||
SpaceId: spaceId,
|
SpaceId: spaceId,
|
||||||
Seed: spaceSettingsSeed,
|
Seed: spaceSettingsSeed,
|
||||||
ChangeType: SpaceSettingsChangeType,
|
ChangeType: SpaceReserved,
|
||||||
Timestamp: time.Now().UnixNano(),
|
Timestamp: time.Now().Unix(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -146,9 +147,10 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
|
|||||||
|
|
||||||
// preparing header and space id
|
// preparing header and space id
|
||||||
header := &spacesyncproto.SpaceHeader{
|
header := &spacesyncproto.SpaceHeader{
|
||||||
Identity: identity,
|
Identity: identity,
|
||||||
SpaceType: SpaceTypeDerived,
|
SpaceType: payload.SpaceType,
|
||||||
ReplicationKey: repKey,
|
SpaceHeaderPayload: payload.SpacePayload,
|
||||||
|
ReplicationKey: repKey,
|
||||||
}
|
}
|
||||||
marshalled, err := header.Marshal()
|
marshalled, err := header.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -201,7 +203,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
|
|||||||
Identity: aclRoot.Identity,
|
Identity: aclRoot.Identity,
|
||||||
SigningKey: payload.SigningKey,
|
SigningKey: payload.SigningKey,
|
||||||
SpaceId: spaceId,
|
SpaceId: spaceId,
|
||||||
ChangeType: SpaceSettingsChangeType,
|
ChangeType: SpaceReserved,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -48,7 +48,7 @@ func (s *stateBuilder) Build(tr objecttree.ObjectTree, oldState *State) (state *
|
|||||||
|
|
||||||
func (s *stateBuilder) processChange(change *objecttree.Change, rootId string, state *State) *State {
|
func (s *stateBuilder) processChange(change *objecttree.Change, rootId string, state *State) *State {
|
||||||
// ignoring root change which has empty model or startId change
|
// ignoring root change which has empty model or startId change
|
||||||
if change.Model == nil || state.LastIteratedId == change.Id {
|
if len(change.PreviousIds) == 0 || state.LastIteratedId == change.Id {
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,7 @@ func TestStateBuilder_ProcessChange(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("changeId is equal to rootId", func(t *testing.T) {
|
t.Run("changeId is equal to rootId", func(t *testing.T) {
|
||||||
ch := &objecttree.Change{}
|
ch := &objecttree.Change{}
|
||||||
|
ch.PreviousIds = []string{"someId"}
|
||||||
ch.Model = &spacesyncproto.SettingsData{
|
ch.Model = &spacesyncproto.SettingsData{
|
||||||
Snapshot: &spacesyncproto.SpaceSettingsSnapshot{
|
Snapshot: &spacesyncproto.SpaceSettingsSnapshot{
|
||||||
DeletedIds: []string{"id1", "id2"},
|
DeletedIds: []string{"id1", "id2"},
|
||||||
@ -56,6 +57,7 @@ func TestStateBuilder_ProcessChange(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("changeId is not equal to lastIteratedId or rootId", func(t *testing.T) {
|
t.Run("changeId is not equal to lastIteratedId or rootId", func(t *testing.T) {
|
||||||
ch := &objecttree.Change{}
|
ch := &objecttree.Change{}
|
||||||
|
ch.PreviousIds = []string{"someId"}
|
||||||
ch.Model = &spacesyncproto.SettingsData{
|
ch.Model = &spacesyncproto.SettingsData{
|
||||||
Content: []*spacesyncproto.SpaceSettingsContent{
|
Content: []*spacesyncproto.SpaceSettingsContent{
|
||||||
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{
|
{Value: &spacesyncproto.SpaceSettingsContent_ObjectDelete{
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/any-sync/accountservice"
|
"github.com/anytypeio/any-sync/accountservice"
|
||||||
"github.com/anytypeio/any-sync/app/logger"
|
"github.com/anytypeio/any-sync/app/logger"
|
||||||
"github.com/anytypeio/any-sync/app/ocache"
|
|
||||||
"github.com/anytypeio/any-sync/commonspace/headsync"
|
"github.com/anytypeio/any-sync/commonspace/headsync"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/list"
|
||||||
"github.com/anytypeio/any-sync/commonspace/object/acl/syncacl"
|
"github.com/anytypeio/any-sync/commonspace/object/acl/syncacl"
|
||||||
@ -52,6 +51,8 @@ type SpaceCreatePayload struct {
|
|||||||
ReadKey []byte
|
ReadKey []byte
|
||||||
// ReplicationKey is a key which is to be used to determine the node where the space should be held
|
// ReplicationKey is a key which is to be used to determine the node where the space should be held
|
||||||
ReplicationKey uint64
|
ReplicationKey uint64
|
||||||
|
// SpacePayload is an arbitrary payload related to space type
|
||||||
|
SpacePayload []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandleMessage struct {
|
type HandleMessage struct {
|
||||||
@ -61,11 +62,11 @@ type HandleMessage struct {
|
|||||||
Message *spacesyncproto.ObjectSyncMessage
|
Message *spacesyncproto.ObjectSyncMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpaceTypeDerived = "derived.space"
|
|
||||||
|
|
||||||
type SpaceDerivePayload struct {
|
type SpaceDerivePayload struct {
|
||||||
SigningKey signingkey.PrivKey
|
SigningKey signingkey.PrivKey
|
||||||
EncryptionKey encryptionkey.PrivKey
|
EncryptionKey encryptionkey.PrivKey
|
||||||
|
SpaceType string
|
||||||
|
SpacePayload []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type SpaceDescription struct {
|
type SpaceDescription struct {
|
||||||
@ -81,9 +82,6 @@ func NewSpaceId(id string, repKey uint64) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Space interface {
|
type Space interface {
|
||||||
ocache.ObjectLocker
|
|
||||||
ocache.ObjectLastUsage
|
|
||||||
|
|
||||||
Id() string
|
Id() string
|
||||||
Init(ctx context.Context) error
|
Init(ctx context.Context) error
|
||||||
|
|
||||||
@ -108,6 +106,7 @@ type Space interface {
|
|||||||
|
|
||||||
HandleMessage(ctx context.Context, msg HandleMessage) (err error)
|
HandleMessage(ctx context.Context, msg HandleMessage) (err error)
|
||||||
|
|
||||||
|
TryClose(objectTTL time.Duration) (close bool, err error)
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,16 +133,6 @@ type space struct {
|
|||||||
treesUsed *atomic.Int32
|
treesUsed *atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) LastUsage() time.Time {
|
|
||||||
return s.objectSync.LastUsage()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *space) Locked() bool {
|
|
||||||
locked := s.treesUsed.Load() > 1
|
|
||||||
log.With(zap.Int32("trees used", s.treesUsed.Load()), zap.Bool("locked", locked), zap.String("spaceId", s.id)).Debug("space lock status check")
|
|
||||||
return locked
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *space) Id() string {
|
func (s *space) Id() string {
|
||||||
return s.id
|
return s.id
|
||||||
}
|
}
|
||||||
@ -462,3 +451,15 @@ func (s *space) Close() error {
|
|||||||
log.With(zap.String("id", s.id)).Debug("space closed")
|
log.With(zap.String("id", s.id)).Debug("space closed")
|
||||||
return mError.Err()
|
return mError.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *space) TryClose(objectTTL time.Duration) (close bool, err error) {
|
||||||
|
if time.Now().Sub(s.objectSync.LastUsage()) < objectTTL {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
locked := s.treesUsed.Load() > 1
|
||||||
|
log.With(zap.Int32("trees used", s.treesUsed.Load()), zap.Bool("locked", locked), zap.String("spaceId", s.id)).Debug("space lock status check")
|
||||||
|
if locked {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, s.Close()
|
||||||
|
}
|
||||||
|
|||||||
@ -98,6 +98,7 @@ message SpaceHeader {
|
|||||||
string spaceType = 3;
|
string spaceType = 3;
|
||||||
uint64 replicationKey = 4;
|
uint64 replicationKey = 4;
|
||||||
bytes seed = 5;
|
bytes seed = 5;
|
||||||
|
bytes spaceHeaderPayload = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawSpaceHeader is raw header for SpaceHeader
|
// RawSpaceHeader is raw header for SpaceHeader
|
||||||
|
|||||||
@ -694,11 +694,12 @@ func (m *SpacePayload) GetSpaceSettingsPayloadId() string {
|
|||||||
|
|
||||||
// SpaceHeader is a header for a space
|
// SpaceHeader is a header for a space
|
||||||
type SpaceHeader struct {
|
type SpaceHeader struct {
|
||||||
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
|
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
|
||||||
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||||
SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"`
|
SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"`
|
||||||
ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"`
|
ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"`
|
||||||
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
|
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
|
||||||
|
SpaceHeaderPayload []byte `protobuf:"bytes,6,opt,name=spaceHeaderPayload,proto3" json:"spaceHeaderPayload,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
|
func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
|
||||||
@ -769,6 +770,13 @@ func (m *SpaceHeader) GetSeed() []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetSpaceHeaderPayload() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.SpaceHeaderPayload
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RawSpaceHeader is raw header for SpaceHeader
|
// RawSpaceHeader is raw header for SpaceHeader
|
||||||
type RawSpaceHeader struct {
|
type RawSpaceHeader struct {
|
||||||
SpaceHeader []byte `protobuf:"bytes,1,opt,name=spaceHeader,proto3" json:"spaceHeader,omitempty"`
|
SpaceHeader []byte `protobuf:"bytes,1,opt,name=spaceHeader,proto3" json:"spaceHeader,omitempty"`
|
||||||
@ -1240,72 +1248,73 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_80e49f1f4ac27799 = []byte{
|
var fileDescriptor_80e49f1f4ac27799 = []byte{
|
||||||
// 1030 bytes of a gzipped FileDescriptorProto
|
// 1042 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x4b, 0x6f, 0xdb, 0x46,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
|
||||||
0x10, 0x16, 0xe9, 0xa7, 0xc6, 0xb2, 0xcc, 0x6c, 0x9c, 0x44, 0x55, 0x0c, 0x45, 0x58, 0x14, 0x85,
|
0x14, 0xf7, 0x6e, 0xd2, 0x24, 0x7e, 0x71, 0x9c, 0xed, 0x34, 0x6d, 0x8d, 0x1b, 0xb9, 0xd6, 0x08,
|
||||||
0x91, 0x43, 0x1e, 0x72, 0x51, 0x20, 0x69, 0x7b, 0x48, 0x64, 0xa7, 0x11, 0x8a, 0xd4, 0xc6, 0xaa,
|
0xa1, 0xa8, 0x87, 0xb4, 0x75, 0x10, 0x52, 0x0b, 0x1c, 0x5a, 0x27, 0xa5, 0x16, 0x2a, 0x89, 0xc6,
|
||||||
0x41, 0x81, 0x02, 0x39, 0xac, 0xc9, 0xb1, 0xc4, 0x96, 0x22, 0x59, 0xee, 0xaa, 0xb6, 0x8e, 0x3d,
|
0x54, 0x48, 0x48, 0x3d, 0x4c, 0x76, 0x5f, 0xec, 0x85, 0xf5, 0xee, 0xb2, 0x33, 0x26, 0xf1, 0x91,
|
||||||
0xf5, 0xda, 0x73, 0x7b, 0xea, 0x7f, 0xe8, 0x8f, 0xe8, 0x31, 0xc7, 0x1e, 0x0b, 0xfb, 0x8f, 0x14,
|
0x13, 0x57, 0xce, 0xf0, 0x35, 0xf8, 0x10, 0x1c, 0xcb, 0x8d, 0x23, 0x4a, 0xbe, 0x08, 0x9a, 0xd9,
|
||||||
0xbb, 0x5c, 0x3e, 0x24, 0x51, 0x01, 0x7a, 0x91, 0xb9, 0xdf, 0xcc, 0x7c, 0xf3, 0xda, 0x9d, 0x31,
|
0xd9, 0x3f, 0xb6, 0xd7, 0x95, 0xb8, 0x38, 0x3b, 0xbf, 0xf7, 0xde, 0xef, 0xfd, 0x9b, 0x79, 0x2f,
|
||||||
0x3c, 0x75, 0xa3, 0xc9, 0x24, 0x0a, 0x45, 0xcc, 0x5d, 0x7c, 0xac, 0x7f, 0xc5, 0x2c, 0x74, 0xe3,
|
0xf0, 0xd4, 0x8d, 0x26, 0x93, 0x28, 0x14, 0x31, 0x77, 0xf1, 0xb1, 0xfe, 0x15, 0xb3, 0xd0, 0x8d,
|
||||||
0x24, 0x92, 0xd1, 0x63, 0xfd, 0x2b, 0x0a, 0xf4, 0x91, 0x06, 0x48, 0x3d, 0x07, 0xe8, 0x00, 0x76,
|
0x93, 0x48, 0x46, 0x8f, 0xf5, 0xaf, 0x28, 0xd0, 0x43, 0x0d, 0x90, 0x7a, 0x0e, 0xd0, 0x01, 0xec,
|
||||||
0x5f, 0x23, 0xf7, 0x86, 0xb3, 0xd0, 0x65, 0x3c, 0x1c, 0x21, 0x21, 0xb0, 0x7e, 0x91, 0x44, 0x93,
|
0xbc, 0x46, 0xee, 0x0d, 0x67, 0xa1, 0xcb, 0x78, 0x38, 0x42, 0x42, 0x60, 0xfd, 0x22, 0x89, 0x26,
|
||||||
0x96, 0xd5, 0xb5, 0x0e, 0xd7, 0x99, 0xfe, 0x26, 0x4d, 0xb0, 0x65, 0xd4, 0xb2, 0x35, 0x62, 0xcb,
|
0x2d, 0xab, 0x6b, 0x1d, 0xac, 0x33, 0xfd, 0x4d, 0x9a, 0x60, 0xcb, 0xa8, 0x65, 0x6b, 0xc4, 0x96,
|
||||||
0x88, 0xec, 0xc3, 0x46, 0xe0, 0x4f, 0x7c, 0xd9, 0x5a, 0xeb, 0x5a, 0x87, 0xbb, 0x2c, 0x3d, 0xd0,
|
0x11, 0xd9, 0x83, 0x5b, 0x81, 0x3f, 0xf1, 0x65, 0x6b, 0xad, 0x6b, 0x1d, 0xec, 0xb0, 0xf4, 0x40,
|
||||||
0x2b, 0x68, 0xe6, 0x54, 0x28, 0xa6, 0x81, 0x54, 0x5c, 0x63, 0x2e, 0xc6, 0x9a, 0xab, 0xc1, 0xf4,
|
0xaf, 0xa0, 0x99, 0x53, 0xa1, 0x98, 0x06, 0x52, 0x71, 0x8d, 0xb9, 0x18, 0x6b, 0xae, 0x06, 0xd3,
|
||||||
0x37, 0xf9, 0x02, 0xb6, 0x31, 0xc0, 0x09, 0x86, 0x52, 0xb4, 0xec, 0xee, 0xda, 0xe1, 0x4e, 0xaf,
|
0xdf, 0xe4, 0x0b, 0xd8, 0xc2, 0x00, 0x27, 0x18, 0x4a, 0xd1, 0xb2, 0xbb, 0x6b, 0x07, 0xdb, 0xbd,
|
||||||
0xfb, 0xa8, 0x88, 0x6f, 0x9e, 0xe0, 0x24, 0x55, 0x64, 0xb9, 0x85, 0xf2, 0xec, 0x46, 0xd3, 0x30,
|
0xee, 0x61, 0x11, 0xdf, 0x3c, 0xc1, 0x49, 0xaa, 0xc8, 0x72, 0x0b, 0xe5, 0xd9, 0x8d, 0xa6, 0x61,
|
||||||
0xf7, 0xac, 0x0f, 0xf4, 0x73, 0xb8, 0x53, 0x69, 0xa8, 0x02, 0xf7, 0x3d, 0xed, 0xbe, 0xce, 0x6c,
|
0xee, 0x59, 0x1f, 0xe8, 0xe7, 0x70, 0xb7, 0xd2, 0x50, 0x05, 0xee, 0x7b, 0xda, 0x7d, 0x9d, 0xd9,
|
||||||
0xdf, 0xd3, 0x01, 0x21, 0xf7, 0x74, 0x2a, 0x75, 0xa6, 0xbf, 0xe9, 0x3b, 0xd8, 0x2b, 0x8c, 0x7f,
|
0xbe, 0xa7, 0x03, 0x42, 0xee, 0xe9, 0x54, 0xea, 0x4c, 0x7f, 0xd3, 0x77, 0xb0, 0x5b, 0x18, 0xff,
|
||||||
0x9a, 0xa2, 0x90, 0xa4, 0x05, 0x5b, 0x3a, 0xa4, 0x41, 0x66, 0x9b, 0x1d, 0xc9, 0x13, 0xd8, 0x4c,
|
0x34, 0x45, 0x21, 0x49, 0x0b, 0x36, 0x75, 0x48, 0x83, 0xcc, 0x36, 0x3b, 0x92, 0x27, 0xb0, 0x91,
|
||||||
0x54, 0x99, 0xb2, 0xd8, 0x5b, 0x55, 0xb1, 0x2b, 0x05, 0x66, 0xf4, 0xe8, 0x57, 0xe0, 0x94, 0x62,
|
0xa8, 0x32, 0x65, 0xb1, 0xb7, 0xaa, 0x62, 0x57, 0x0a, 0xcc, 0xe8, 0xd1, 0xaf, 0xc0, 0x29, 0xc5,
|
||||||
0x8b, 0xa3, 0x50, 0x20, 0x39, 0x82, 0xad, 0x44, 0xc7, 0x29, 0x5a, 0x96, 0xa6, 0xf9, 0x68, 0x65,
|
0x16, 0x47, 0xa1, 0x40, 0x72, 0x04, 0x9b, 0x89, 0x8e, 0x53, 0xb4, 0x2c, 0x4d, 0xf3, 0xd1, 0xca,
|
||||||
0x09, 0x58, 0xa6, 0x49, 0xff, 0xb0, 0xe0, 0xd6, 0xe9, 0xf9, 0x0f, 0xe8, 0x4a, 0x25, 0x7d, 0x83,
|
0x12, 0xb0, 0x4c, 0x93, 0xfe, 0x61, 0xc1, 0xed, 0xd3, 0xf3, 0x1f, 0xd0, 0x95, 0x4a, 0xfa, 0x06,
|
||||||
0x42, 0xf0, 0x11, 0x7e, 0x20, 0xd4, 0x03, 0xa8, 0x27, 0x69, 0x3e, 0x83, 0x2c, 0xe1, 0x02, 0x50,
|
0x85, 0xe0, 0x23, 0xfc, 0x40, 0xa8, 0xfb, 0x50, 0x4f, 0xd2, 0x7c, 0x06, 0x59, 0xc2, 0x05, 0xa0,
|
||||||
0x76, 0x09, 0xc6, 0xc1, 0x6c, 0xe0, 0xe9, 0x52, 0xd6, 0x59, 0x76, 0x54, 0x92, 0x98, 0xcf, 0x82,
|
0xec, 0x12, 0x8c, 0x83, 0xd9, 0xc0, 0xd3, 0xa5, 0xac, 0xb3, 0xec, 0xa8, 0x24, 0x31, 0x9f, 0x05,
|
||||||
0x88, 0x7b, 0xad, 0x75, 0xdd, 0xb7, 0xec, 0x48, 0xda, 0xb0, 0x1d, 0xe9, 0x00, 0x06, 0x5e, 0x6b,
|
0x11, 0xf7, 0x5a, 0xeb, 0xba, 0x6f, 0xd9, 0x91, 0xb4, 0x61, 0x2b, 0xd2, 0x01, 0x0c, 0xbc, 0xd6,
|
||||||
0x43, 0x1b, 0xe5, 0x67, 0x8a, 0xe0, 0x0c, 0x95, 0xe3, 0xb3, 0xa9, 0x18, 0x67, 0x65, 0x7c, 0x5a,
|
0x2d, 0x6d, 0x94, 0x9f, 0x29, 0x82, 0x33, 0x54, 0x8e, 0xcf, 0xa6, 0x62, 0x9c, 0x95, 0xf1, 0x69,
|
||||||
0x30, 0xa9, 0xd8, 0x76, 0x7a, 0xf7, 0x4a, 0x69, 0xa6, 0xda, 0xa9, 0xb8, 0x70, 0xd1, 0x01, 0xe8,
|
0xc1, 0xa4, 0x62, 0xdb, 0xee, 0xdd, 0x2f, 0xa5, 0x99, 0x6a, 0xa7, 0xe2, 0xc2, 0x45, 0x07, 0xa0,
|
||||||
0x27, 0xe8, 0x61, 0x28, 0x7d, 0x1e, 0xe8, 0xa8, 0x1b, 0xac, 0x84, 0xd0, 0xdb, 0x70, 0xab, 0xe4,
|
0x9f, 0xa0, 0x87, 0xa1, 0xf4, 0x79, 0xa0, 0xa3, 0x6e, 0xb0, 0x12, 0x42, 0xef, 0xc0, 0xed, 0x92,
|
||||||
0x26, 0x2d, 0x27, 0xa5, 0xb9, 0xef, 0x20, 0xc8, 0x7c, 0x2f, 0x74, 0x9e, 0xbe, 0xca, 0x0d, 0x95,
|
0x9b, 0xb4, 0x9c, 0x94, 0xe6, 0xbe, 0x83, 0x20, 0xf3, 0xbd, 0xd0, 0x79, 0xfa, 0x2a, 0x37, 0x54,
|
||||||
0x8e, 0xe9, 0xc3, 0xff, 0x0f, 0x90, 0xfe, 0x62, 0x43, 0xa3, 0x2c, 0x21, 0x2f, 0x60, 0x47, 0xdb,
|
0x3a, 0xa6, 0x0f, 0xff, 0x3f, 0x40, 0xfa, 0x8b, 0x0d, 0x8d, 0xb2, 0x84, 0xbc, 0x80, 0x6d, 0x6d,
|
||||||
0xa8, 0xb6, 0x61, 0x62, 0x78, 0x1e, 0x94, 0x78, 0x18, 0xbf, 0x1c, 0x16, 0x0a, 0xdf, 0xf9, 0x72,
|
0xa3, 0xda, 0x86, 0x89, 0xe1, 0x79, 0x58, 0xe2, 0x61, 0xfc, 0x72, 0x58, 0x28, 0x7c, 0xe7, 0xcb,
|
||||||
0x3c, 0xf0, 0x58, 0xd9, 0x46, 0x25, 0xcd, 0xdd, 0xc0, 0x10, 0x66, 0x49, 0x17, 0x08, 0xa1, 0xd0,
|
0xf1, 0xc0, 0x63, 0x65, 0x1b, 0x95, 0x34, 0x77, 0x03, 0x43, 0x98, 0x25, 0x5d, 0x20, 0x84, 0x42,
|
||||||
0x28, 0x4e, 0x79, 0xc3, 0xe6, 0x30, 0xd2, 0x83, 0x7d, 0x4d, 0x39, 0x44, 0x29, 0xfd, 0x70, 0x24,
|
0xa3, 0x38, 0xe5, 0x0d, 0x9b, 0xc3, 0x48, 0x0f, 0xf6, 0x34, 0xe5, 0x10, 0xa5, 0xf4, 0xc3, 0x91,
|
||||||
0xce, 0xe6, 0x5a, 0x58, 0x29, 0x23, 0x9f, 0xc1, 0xdd, 0x2a, 0x3c, 0xef, 0xee, 0x0a, 0x29, 0xfd,
|
0x38, 0x9b, 0x6b, 0x61, 0xa5, 0x8c, 0x7c, 0x06, 0xf7, 0xaa, 0xf0, 0xbc, 0xbb, 0x2b, 0xa4, 0xf4,
|
||||||
0xd3, 0x82, 0x9d, 0x52, 0x4a, 0xea, 0x5e, 0xf8, 0xba, 0x41, 0x72, 0x66, 0x9e, 0x7a, 0x7e, 0x56,
|
0x6f, 0x0b, 0xb6, 0x4b, 0x29, 0xa9, 0x7b, 0xe1, 0xeb, 0x06, 0xc9, 0x99, 0x79, 0xea, 0xf9, 0x59,
|
||||||
0xb7, 0x50, 0xfa, 0x13, 0x14, 0x92, 0x4f, 0x62, 0x9d, 0xda, 0x1a, 0x2b, 0x00, 0x25, 0xd5, 0x3e,
|
0xdd, 0x42, 0xe9, 0x4f, 0x50, 0x48, 0x3e, 0x89, 0x75, 0x6a, 0x6b, 0xac, 0x00, 0x94, 0x54, 0xfb,
|
||||||
0xbe, 0x9d, 0xc5, 0x68, 0xd2, 0x2a, 0x00, 0xf2, 0x09, 0x34, 0xd5, 0xa5, 0xf4, 0x5d, 0x2e, 0xfd,
|
0xf8, 0x76, 0x16, 0xa3, 0x49, 0xab, 0x00, 0xc8, 0x27, 0xd0, 0x54, 0x97, 0xd2, 0x77, 0xb9, 0xf4,
|
||||||
0x28, 0xfc, 0x1a, 0x67, 0x3a, 0x9b, 0x75, 0xb6, 0x80, 0xaa, 0x57, 0x2d, 0x10, 0xd3, 0xa8, 0x1b,
|
0xa3, 0xf0, 0x6b, 0x9c, 0xe9, 0x6c, 0xd6, 0xd9, 0x02, 0xaa, 0x5e, 0xb5, 0x40, 0x4c, 0xa3, 0x6e,
|
||||||
0x4c, 0x7f, 0xd3, 0x33, 0x68, 0xce, 0x17, 0x9e, 0x74, 0x97, 0x1b, 0xd5, 0x98, 0xef, 0x83, 0x8a,
|
0x30, 0xfd, 0x4d, 0x0e, 0x81, 0x94, 0x4a, 0x9c, 0x55, 0x63, 0x43, 0x6b, 0x54, 0x48, 0xe8, 0x19,
|
||||||
0xc6, 0x1f, 0x85, 0x5c, 0x4e, 0x13, 0x34, 0x6d, 0x28, 0x00, 0x7a, 0x0c, 0xfb, 0x55, 0xad, 0xd4,
|
0x34, 0xe7, 0x1b, 0x45, 0xba, 0xcb, 0x8d, 0x6d, 0xcc, 0xf7, 0x4d, 0x45, 0xef, 0x8f, 0x42, 0x2e,
|
||||||
0xef, 0x8c, 0x5f, 0xce, 0xb1, 0x16, 0x80, 0xb9, 0x87, 0x76, 0x7e, 0x0f, 0x7f, 0xb7, 0x60, 0x7f,
|
0xa7, 0x09, 0x9a, 0xb6, 0x15, 0x00, 0x3d, 0x86, 0xbd, 0xaa, 0xd6, 0xeb, 0x77, 0xc9, 0x2f, 0xe7,
|
||||||
0x58, 0x2e, 0x6b, 0x3f, 0x0a, 0xa5, 0x1a, 0x55, 0x5f, 0x42, 0x23, 0x7d, 0x4c, 0xc7, 0x18, 0xa0,
|
0x58, 0x0b, 0xc0, 0xdc, 0x5b, 0x3b, 0xbf, 0xb7, 0xbf, 0x5b, 0xb0, 0x37, 0x2c, 0xb7, 0xa1, 0x1f,
|
||||||
0xc4, 0x8a, 0x0b, 0x79, 0x5a, 0x12, 0xbf, 0xae, 0xb1, 0x39, 0x75, 0xf2, 0xdc, 0x64, 0x67, 0xac,
|
0x85, 0x52, 0x8d, 0xb6, 0x2f, 0xa1, 0x91, 0x3e, 0xbe, 0x63, 0x0c, 0x50, 0x62, 0xc5, 0x05, 0x3e,
|
||||||
0x6d, 0x6d, 0x7d, 0x77, 0xf1, 0x3a, 0xe7, 0xc6, 0x65, 0xe5, 0x97, 0x5b, 0xb0, 0xf1, 0x33, 0x0f,
|
0x2d, 0x89, 0x5f, 0xd7, 0xd8, 0x9c, 0x3a, 0x79, 0x6e, 0xb2, 0x33, 0xd6, 0xb6, 0xb6, 0xbe, 0xb7,
|
||||||
0xa6, 0x48, 0x3b, 0xd0, 0x28, 0x3b, 0x59, 0x7a, 0x44, 0x47, 0xa6, 0xef, 0x46, 0xfc, 0x31, 0xec,
|
0x78, 0xfd, 0x73, 0xe3, 0xb2, 0xf2, 0xcb, 0x4d, 0xb8, 0xf5, 0x33, 0x0f, 0xa6, 0x48, 0x3b, 0xd0,
|
||||||
0x7a, 0xfa, 0x2b, 0x39, 0x43, 0x4c, 0xf2, 0x09, 0x34, 0x0f, 0xd2, 0x77, 0x70, 0x67, 0x2e, 0xe1,
|
0x28, 0x3b, 0x59, 0x7a, 0x74, 0x47, 0xe6, 0x9e, 0x18, 0xf1, 0xc7, 0xb0, 0xe3, 0xe9, 0xaf, 0xe4,
|
||||||
0x61, 0xc8, 0x63, 0x31, 0x8e, 0xa4, 0xba, 0xf6, 0xa9, 0xa6, 0x37, 0xf0, 0xd2, 0x41, 0x58, 0x67,
|
0x0c, 0x31, 0xc9, 0x27, 0xd6, 0x3c, 0x48, 0xdf, 0xc1, 0xdd, 0xb9, 0x84, 0x87, 0x21, 0x8f, 0xc5,
|
||||||
0x25, 0x64, 0x99, 0xde, 0xae, 0xa2, 0xff, 0xd5, 0x82, 0x46, 0x46, 0x7d, 0xcc, 0x25, 0x27, 0xcf,
|
0x38, 0x92, 0xea, 0x99, 0xa4, 0x9a, 0xde, 0xc0, 0x4b, 0x07, 0x67, 0x9d, 0x95, 0x90, 0x65, 0x7a,
|
||||||
0x60, 0xcb, 0x4d, 0x6b, 0x6a, 0x86, 0xeb, 0x83, 0xc5, 0x2a, 0x2c, 0x94, 0x9e, 0x65, 0xfa, 0x6a,
|
0xbb, 0x8a, 0xfe, 0x57, 0x0b, 0x1a, 0x19, 0xf5, 0x31, 0x97, 0x9c, 0x3c, 0x83, 0x4d, 0x37, 0xad,
|
||||||
0x37, 0x09, 0x13, 0x9d, 0xa9, 0x60, 0x77, 0x95, 0x6d, 0x96, 0x05, 0xcb, 0x2d, 0xe8, 0x8f, 0x66,
|
0xa9, 0x19, 0xc6, 0x0f, 0x17, 0xab, 0xb0, 0x50, 0x7a, 0x96, 0xe9, 0xab, 0x5d, 0x26, 0x4c, 0x74,
|
||||||
0xc4, 0x0c, 0xa7, 0xe7, 0xc2, 0x4d, 0xfc, 0x58, 0x5d, 0x4f, 0xf5, 0x36, 0xcc, 0x40, 0xce, 0x52,
|
0xa6, 0x82, 0xdd, 0x55, 0xb6, 0x59, 0x16, 0x2c, 0xb7, 0xa0, 0x3f, 0x9a, 0x91, 0x34, 0x9c, 0x9e,
|
||||||
0xcc, 0xcf, 0xe4, 0x39, 0x6c, 0x72, 0x57, 0x69, 0x69, 0x67, 0xcd, 0x1e, 0x5d, 0x72, 0x56, 0x62,
|
0x0b, 0x37, 0xf1, 0x63, 0x75, 0x9d, 0xd5, 0x5b, 0x32, 0x03, 0x3c, 0x4b, 0x31, 0x3f, 0x93, 0xe7,
|
||||||
0x7a, 0xa1, 0x35, 0x99, 0xb1, 0x78, 0x78, 0x09, 0xdb, 0x27, 0x49, 0xd2, 0x8f, 0x3c, 0x14, 0xa4,
|
0xb0, 0xc1, 0x5d, 0xa5, 0xa5, 0x9d, 0x35, 0x7b, 0x74, 0xc9, 0x59, 0x89, 0xe9, 0x85, 0xd6, 0x64,
|
||||||
0x09, 0xf0, 0x36, 0xc4, 0xab, 0x18, 0x5d, 0x89, 0x9e, 0x53, 0x23, 0x8e, 0x19, 0x51, 0x6f, 0x7c,
|
0xc6, 0xe2, 0xd1, 0x25, 0x6c, 0x9d, 0x24, 0x49, 0x3f, 0xf2, 0x50, 0x90, 0x26, 0xc0, 0xdb, 0x10,
|
||||||
0x21, 0xfc, 0x70, 0xe4, 0x58, 0x64, 0xcf, 0x34, 0xee, 0xe4, 0xca, 0x17, 0x52, 0x38, 0x36, 0xb9,
|
0xaf, 0x62, 0x74, 0x25, 0x7a, 0x4e, 0x8d, 0x38, 0x66, 0xa4, 0xbd, 0xf1, 0x85, 0xf0, 0xc3, 0x91,
|
||||||
0x0d, 0x7b, 0x1a, 0xf8, 0x26, 0x92, 0x83, 0xb0, 0xcf, 0xdd, 0x31, 0x3a, 0x6b, 0x84, 0x40, 0x53,
|
0x63, 0x91, 0x5d, 0xd3, 0xb8, 0x93, 0x2b, 0x5f, 0x48, 0xe1, 0xd8, 0xe4, 0x0e, 0xec, 0x6a, 0xe0,
|
||||||
0x83, 0x03, 0x91, 0x36, 0xd8, 0x73, 0xd6, 0x95, 0xe5, 0x49, 0x92, 0x44, 0xc9, 0xe9, 0xc5, 0x85,
|
0x9b, 0x48, 0x0e, 0xc2, 0x3e, 0x77, 0xc7, 0xe8, 0xac, 0x11, 0x02, 0x4d, 0x0d, 0x0e, 0x44, 0xda,
|
||||||
0x40, 0xe9, 0x78, 0x0f, 0x9f, 0xc1, 0xbd, 0x15, 0xb1, 0x91, 0x5d, 0xa8, 0x1b, 0xf4, 0x1c, 0x9d,
|
0x60, 0xcf, 0x59, 0x57, 0x96, 0x27, 0x49, 0x12, 0x25, 0xa7, 0x17, 0x17, 0x02, 0xa5, 0xe3, 0x3d,
|
||||||
0x9a, 0x32, 0x7d, 0x1b, 0x8a, 0x1c, 0xb0, 0x7a, 0x7f, 0xd9, 0x50, 0x4f, 0x6d, 0x67, 0xa1, 0x4b,
|
0x7a, 0x06, 0xf7, 0x57, 0xc4, 0x46, 0x76, 0xa0, 0x6e, 0xd0, 0x73, 0x74, 0x6a, 0xca, 0xf4, 0x6d,
|
||||||
0xfa, 0xb0, 0x9d, 0xad, 0x3a, 0xd2, 0xae, 0xdc, 0x7f, 0x7a, 0x92, 0xb7, 0xef, 0x57, 0xef, 0xc6,
|
0x28, 0x72, 0xc0, 0xea, 0xfd, 0x69, 0x43, 0x3d, 0xb5, 0x9d, 0x85, 0x2e, 0xe9, 0xc3, 0x56, 0xb6,
|
||||||
0x74, 0x82, 0xbf, 0x32, 0x8c, 0x6a, 0x1f, 0x90, 0xfb, 0x4b, 0xd3, 0xbb, 0x58, 0x46, 0xed, 0x83,
|
0x1a, 0x49, 0xbb, 0x72, 0x5f, 0xea, 0xc9, 0xdf, 0x7e, 0x50, 0xbd, 0x4b, 0xd3, 0x89, 0xff, 0xca,
|
||||||
0x6a, 0xe1, 0x12, 0x4f, 0x10, 0x54, 0xf1, 0xe4, 0x8b, 0xa5, 0x8a, 0xa7, 0xb4, 0x51, 0x18, 0x38,
|
0x30, 0xaa, 0xfd, 0x41, 0x1e, 0x2c, 0x4d, 0xfb, 0x62, 0x79, 0xb5, 0xf7, 0xab, 0x85, 0x4b, 0x3c,
|
||||||
0xc5, 0x8e, 0x1e, 0xca, 0x04, 0xf9, 0x84, 0x1c, 0x2c, 0xbd, 0xe1, 0xd2, 0x02, 0x6f, 0x7f, 0x50,
|
0x41, 0x50, 0xc5, 0x93, 0x2f, 0xa2, 0x2a, 0x9e, 0xd2, 0x06, 0x62, 0xe0, 0x14, 0x3b, 0x7d, 0x28,
|
||||||
0x7a, 0x68, 0x3d, 0xb1, 0x5e, 0x7e, 0xfa, 0xf7, 0x75, 0xc7, 0x7a, 0x7f, 0xdd, 0xb1, 0xfe, 0xbd,
|
0x13, 0xe4, 0x13, 0xb2, 0xbf, 0xf4, 0x86, 0x4b, 0x0b, 0xbf, 0xfd, 0x41, 0xe9, 0x81, 0xf5, 0xc4,
|
||||||
0xee, 0x58, 0xbf, 0xdd, 0x74, 0x6a, 0xef, 0x6f, 0x3a, 0xb5, 0x7f, 0x6e, 0x3a, 0xb5, 0xef, 0xdb,
|
0x7a, 0xf9, 0xe9, 0x5f, 0xd7, 0x1d, 0xeb, 0xfd, 0x75, 0xc7, 0xfa, 0xf7, 0xba, 0x63, 0xfd, 0x76,
|
||||||
0xab, 0xff, 0xf5, 0x3b, 0xdf, 0xd4, 0x7f, 0x8e, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x96,
|
0xd3, 0xa9, 0xbd, 0xbf, 0xe9, 0xd4, 0xfe, 0xb9, 0xe9, 0xd4, 0xbe, 0x6f, 0xaf, 0xfe, 0x57, 0xf1,
|
||||||
0xb3, 0xaa, 0x1f, 0x0a, 0x00, 0x00,
|
0x7c, 0x43, 0xff, 0x39, 0xfa, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x13, 0xff, 0xe7, 0x17, 0x4f, 0x0a,
|
||||||
|
0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
|
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
|
||||||
@ -1784,6 +1793,13 @@ func (m *SpaceHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
if len(m.SpaceHeaderPayload) > 0 {
|
||||||
|
i -= len(m.SpaceHeaderPayload)
|
||||||
|
copy(dAtA[i:], m.SpaceHeaderPayload)
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.SpaceHeaderPayload)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x32
|
||||||
|
}
|
||||||
if len(m.Seed) > 0 {
|
if len(m.Seed) > 0 {
|
||||||
i -= len(m.Seed)
|
i -= len(m.Seed)
|
||||||
copy(dAtA[i:], m.Seed)
|
copy(dAtA[i:], m.Seed)
|
||||||
@ -2387,6 +2403,10 @@ func (m *SpaceHeader) Size() (n int) {
|
|||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 1 + l + sovSpacesync(uint64(l))
|
n += 1 + l + sovSpacesync(uint64(l))
|
||||||
}
|
}
|
||||||
|
l = len(m.SpaceHeaderPayload)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovSpacesync(uint64(l))
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4041,6 +4061,40 @@ func (m *SpaceHeader) Unmarshal(dAtA []byte) error {
|
|||||||
m.Seed = []byte{}
|
m.Seed = []byte{}
|
||||||
}
|
}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
|
case 6:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field SpaceHeaderPayload", wireType)
|
||||||
|
}
|
||||||
|
var byteLen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
byteLen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if byteLen < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + byteLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.SpaceHeaderPayload = append(m.SpaceHeaderPayload[:0], dAtA[iNdEx:postIndex]...)
|
||||||
|
if m.SpaceHeaderPayload == nil {
|
||||||
|
m.SpaceHeaderPayload = []byte{}
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
skippy, err := skipSpacesync(dAtA[iNdEx:])
|
skippy, err := skipSpacesync(dAtA[iNdEx:])
|
||||||
|
|||||||
@ -38,11 +38,12 @@ func (m *MockCoordinatorClient) EXPECT() *MockCoordinatorClientMockRecorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ChangeStatus mocks base method.
|
// ChangeStatus mocks base method.
|
||||||
func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *treechangeproto.RawTreeChangeWithId) error {
|
func (m *MockCoordinatorClient) ChangeStatus(arg0 context.Context, arg1 string, arg2 *treechangeproto.RawTreeChangeWithId) (*coordinatorproto.SpaceStatusPayload, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ChangeStatus", arg0, arg1, arg2)
|
ret := m.ctrl.Call(m, "ChangeStatus", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(*coordinatorproto.SpaceStatusPayload)
|
||||||
return ret0
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeStatus indicates an expected call of ChangeStatus.
|
// ChangeStatus indicates an expected call of ChangeStatus.
|
||||||
@ -110,10 +111,10 @@ func (mr *MockCoordinatorClientMockRecorder) SpaceSign(arg0, arg1, arg2 interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
// StatusCheck mocks base method.
|
// StatusCheck mocks base method.
|
||||||
func (m *MockCoordinatorClient) StatusCheck(arg0 context.Context, arg1 string) (*coordinatorproto.SpaceStatusCheckResponse, error) {
|
func (m *MockCoordinatorClient) StatusCheck(arg0 context.Context, arg1 string) (*coordinatorproto.SpaceStatusPayload, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "StatusCheck", arg0, arg1)
|
ret := m.ctrl.Call(m, "StatusCheck", arg0, arg1)
|
||||||
ret0, _ := ret[0].(*coordinatorproto.SpaceStatusCheckResponse)
|
ret0, _ := ret[0].(*coordinatorproto.SpaceStatusPayload)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,11 +25,13 @@ type Peer interface {
|
|||||||
Id() string
|
Id() string
|
||||||
LastUsage() time.Time
|
LastUsage() time.Time
|
||||||
UpdateLastUsage()
|
UpdateLastUsage()
|
||||||
|
TryClose(objectTTL time.Duration) (res bool, err error)
|
||||||
drpc.Conn
|
drpc.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type peer struct {
|
type peer struct {
|
||||||
id string
|
id string
|
||||||
|
ttl time.Duration
|
||||||
lastUsage int64
|
lastUsage int64
|
||||||
sc sec.SecureConn
|
sc sec.SecureConn
|
||||||
drpc.Conn
|
drpc.Conn
|
||||||
@ -76,6 +78,13 @@ func (p *peer) UpdateLastUsage() {
|
|||||||
atomic.StoreInt64(&p.lastUsage, time.Now().Unix())
|
atomic.StoreInt64(&p.lastUsage, time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *peer) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||||
|
if time.Now().Sub(p.LastUsage()) < objectTTL {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, p.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (p *peer) Close() (err error) {
|
func (p *peer) Close() (err error) {
|
||||||
log.Debug("peer close", zap.String("peerId", p.id))
|
log.Debug("peer close", zap.String("peerId", p.id))
|
||||||
return p.Conn.Close()
|
return p.Conn.Close()
|
||||||
|
|||||||
@ -49,7 +49,7 @@ func (p *pool) Get(ctx context.Context, id string) (peer.Peer, error) {
|
|||||||
default:
|
default:
|
||||||
return pr, nil
|
return pr, nil
|
||||||
}
|
}
|
||||||
_, _ = p.cache.Remove(id)
|
_, _ = p.cache.Remove(ctx, id)
|
||||||
return p.Get(ctx, id)
|
return p.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -194,6 +194,10 @@ func (t *testPeer) LastUsage() time.Time {
|
|||||||
|
|
||||||
func (t *testPeer) UpdateLastUsage() {}
|
func (t *testPeer) UpdateLastUsage() {}
|
||||||
|
|
||||||
|
func (t *testPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||||
|
return true, t.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (t *testPeer) Close() error {
|
func (t *testPeer) Close() error {
|
||||||
select {
|
select {
|
||||||
case <-t.closed:
|
case <-t.closed:
|
||||||
|
|||||||
@ -103,6 +103,10 @@ type testPeer struct {
|
|||||||
drpc.Conn
|
drpc.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t testPeer) TryClose(objectTTL time.Duration) (res bool, err error) {
|
||||||
|
return true, t.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (t testPeer) Id() string {
|
func (t testPeer) Id() string {
|
||||||
return t.id
|
return t.id
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user