mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-07 21:47:02 +09:00
94 lines
2.1 KiB
Go
94 lines
2.1 KiB
Go
package acl
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/anyproto/any-sync/commonspace/object/acl/list"
|
|
"github.com/anyproto/any-sync/commonspace/object/acl/liststorage"
|
|
"github.com/anyproto/any-sync/consensus/consensusproto"
|
|
"go.uber.org/atomic"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
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 liststorage.ListStorage
|
|
|
|
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 = liststorage.NewInMemoryAclListStorage(a.id, recs); a.consErr != nil {
|
|
return
|
|
}
|
|
if a.AclList, a.consErr = list.BuildAclListWithIdentity(a.aclService.accountService.Account(), a.store, list.NoOpAcceptorVerifier{}); 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
|
|
}
|