1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-07 21:47:02 +09:00
any-sync/acl/object.go
2025-05-13 15:29:05 +02:00

95 lines
2 KiB
Go

package acl
import (
"context"
"slices"
"sync"
"time"
"go.uber.org/atomic"
"go.uber.org/zap"
"github.com/anyproto/any-sync/commonspace/object/acl/list"
"github.com/anyproto/any-sync/commonspace/object/acl/recordverifier"
"github.com/anyproto/any-sync/consensus/consensusproto"
)
func (as *aclService) newAclObject(ctx context.Context, id string) (*aclObject, error) {
obj := &aclObject{
id: id,
aclService: as,
ready: make(chan struct{}),
}
if err := as.consService.Watch(id, obj); err != nil {
return nil, err
}
select {
case <-obj.ready:
if obj.consErr != nil {
_ = as.consService.UnWatch(id)
return nil, obj.consErr
}
return obj, nil
case <-ctx.Done():
_ = as.consService.UnWatch(id)
return nil, ctx.Err()
}
}
type aclObject struct {
id string
aclService *aclService
store list.Storage
list.AclList
ready chan struct{}
consErr error
lastUsage atomic.Time
mu sync.Mutex
}
func (a *aclObject) AddConsensusRecords(recs []*consensusproto.RawRecordWithId) {
a.mu.Lock()
defer a.mu.Unlock()
slices.Reverse(recs)
if a.store == nil {
defer close(a.ready)
if a.store, a.consErr = list.NewInMemoryStorage(a.id, recs); a.consErr != nil {
return
}
if a.AclList, a.consErr = list.BuildAclListWithIdentity(a.aclService.accountService.Account(), a.store, recordverifier.New()); a.consErr != nil {
return
}
} else {
a.Lock()
defer a.Unlock()
if err := a.AddRawRecords(recs); err != nil {
log.Warn("unable to add consensus records", zap.Error(err), zap.String("spaceId", a.id))
return
}
}
}
func (a *aclObject) AddConsensusError(err error) {
a.mu.Lock()
defer a.mu.Unlock()
if a.store == nil {
a.consErr = err
close(a.ready)
} else {
log.Warn("got consensus error", zap.Error(err))
}
}
func (a *aclObject) Close() (err error) {
return a.aclService.consService.UnWatch(a.id)
}
func (a *aclObject) TryClose(objectTTL time.Duration) (res bool, err error) {
if a.lastUsage.Load().Before(time.Now().Add(-objectTTL)) {
return true, a.Close()
}
return false, nil
}