mirror of
https://github.com/anyproto/any-sync.git
synced 2025-06-08 05:57:03 +09:00
commonfile
This commit is contained in:
parent
a894f42e05
commit
5d3e79e506
37 changed files with 4320 additions and 95 deletions
|
@ -17,6 +17,8 @@ proto:
|
|||
$(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto
|
||||
$(eval PKGMAP := $$(P_TREE_CHANGES),$$(P_ACL_RECORDS))
|
||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. commonspace/spacesyncproto/protos/*.proto
|
||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. commonfile/fileproto/protos/*.proto
|
||||
|
||||
|
||||
test:
|
||||
go test ./... --cover
|
1738
common/commonfile/fileproto/file.pb.go
Normal file
1738
common/commonfile/fileproto/file.pb.go
Normal file
File diff suppressed because it is too large
Load diff
268
common/commonfile/fileproto/file_drpc.pb.go
Normal file
268
common/commonfile/fileproto/file_drpc.pb.go
Normal file
|
@ -0,0 +1,268 @@
|
|||
// Code generated by protoc-gen-go-drpc. DO NOT EDIT.
|
||||
// protoc-gen-go-drpc version: v0.0.32
|
||||
// source: commonfile/fileproto/protos/file.proto
|
||||
|
||||
package fileproto
|
||||
|
||||
import (
|
||||
bytes "bytes"
|
||||
context "context"
|
||||
errors "errors"
|
||||
jsonpb "github.com/gogo/protobuf/jsonpb"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
drpc "storj.io/drpc"
|
||||
drpcerr "storj.io/drpc/drpcerr"
|
||||
)
|
||||
|
||||
type drpcEncoding_File_commonfile_fileproto_protos_file_proto struct{}
|
||||
|
||||
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) Marshal(msg drpc.Message) ([]byte, error) {
|
||||
return proto.Marshal(msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) Unmarshal(buf []byte, msg drpc.Message) error {
|
||||
return proto.Unmarshal(buf, msg.(proto.Message))
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) JSONMarshal(msg drpc.Message) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
err := new(jsonpb.Marshaler).Marshal(&buf, msg.(proto.Message))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (drpcEncoding_File_commonfile_fileproto_protos_file_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error {
|
||||
return jsonpb.Unmarshal(bytes.NewReader(buf), msg.(proto.Message))
|
||||
}
|
||||
|
||||
type DRPCFileClient interface {
|
||||
DRPCConn() drpc.Conn
|
||||
|
||||
GetBlocks(ctx context.Context) (DRPCFile_GetBlocksClient, error)
|
||||
PushBlock(ctx context.Context, in *PushBlockRequest) (*PushBlockResponse, error)
|
||||
DeleteBlocks(ctx context.Context, in *DeleteBlocksRequest) (*DeleteBlocksResponse, error)
|
||||
Check(ctx context.Context, in *CheckRequest) (*CheckResponse, error)
|
||||
}
|
||||
|
||||
type drpcFileClient struct {
|
||||
cc drpc.Conn
|
||||
}
|
||||
|
||||
func NewDRPCFileClient(cc drpc.Conn) DRPCFileClient {
|
||||
return &drpcFileClient{cc}
|
||||
}
|
||||
|
||||
func (c *drpcFileClient) DRPCConn() drpc.Conn { return c.cc }
|
||||
|
||||
func (c *drpcFileClient) GetBlocks(ctx context.Context) (DRPCFile_GetBlocksClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, "/anySpace.File/GetBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &drpcFile_GetBlocksClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type DRPCFile_GetBlocksClient interface {
|
||||
drpc.Stream
|
||||
Send(*GetBlockRequest) error
|
||||
Recv() (*GetBlockResponse, error)
|
||||
}
|
||||
|
||||
type drpcFile_GetBlocksClient struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksClient) Send(m *GetBlockRequest) error {
|
||||
return x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksClient) Recv() (*GetBlockResponse, error) {
|
||||
m := new(GetBlockResponse)
|
||||
if err := x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksClient) RecvMsg(m *GetBlockResponse) error {
|
||||
return x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
|
||||
}
|
||||
|
||||
func (c *drpcFileClient) PushBlock(ctx context.Context, in *PushBlockRequest) (*PushBlockResponse, error) {
|
||||
out := new(PushBlockResponse)
|
||||
err := c.cc.Invoke(ctx, "/anySpace.File/PushBlock", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcFileClient) DeleteBlocks(ctx context.Context, in *DeleteBlocksRequest) (*DeleteBlocksResponse, error) {
|
||||
out := new(DeleteBlocksResponse)
|
||||
err := c.cc.Invoke(ctx, "/anySpace.File/DeleteBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *drpcFileClient) Check(ctx context.Context, in *CheckRequest) (*CheckResponse, error) {
|
||||
out := new(CheckResponse)
|
||||
err := c.cc.Invoke(ctx, "/anySpace.File/Check", drpcEncoding_File_commonfile_fileproto_protos_file_proto{}, in, out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type DRPCFileServer interface {
|
||||
GetBlocks(DRPCFile_GetBlocksStream) error
|
||||
PushBlock(context.Context, *PushBlockRequest) (*PushBlockResponse, error)
|
||||
DeleteBlocks(context.Context, *DeleteBlocksRequest) (*DeleteBlocksResponse, error)
|
||||
Check(context.Context, *CheckRequest) (*CheckResponse, error)
|
||||
}
|
||||
|
||||
type DRPCFileUnimplementedServer struct{}
|
||||
|
||||
func (s *DRPCFileUnimplementedServer) GetBlocks(DRPCFile_GetBlocksStream) error {
|
||||
return drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCFileUnimplementedServer) PushBlock(context.Context, *PushBlockRequest) (*PushBlockResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCFileUnimplementedServer) DeleteBlocks(context.Context, *DeleteBlocksRequest) (*DeleteBlocksResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
func (s *DRPCFileUnimplementedServer) Check(context.Context, *CheckRequest) (*CheckResponse, error) {
|
||||
return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented)
|
||||
}
|
||||
|
||||
type DRPCFileDescription struct{}
|
||||
|
||||
func (DRPCFileDescription) NumMethods() int { return 4 }
|
||||
|
||||
func (DRPCFileDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
|
||||
switch n {
|
||||
case 0:
|
||||
return "/anySpace.File/GetBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return nil, srv.(DRPCFileServer).
|
||||
GetBlocks(
|
||||
&drpcFile_GetBlocksStream{in1.(drpc.Stream)},
|
||||
)
|
||||
}, DRPCFileServer.GetBlocks, true
|
||||
case 1:
|
||||
return "/anySpace.File/PushBlock", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCFileServer).
|
||||
PushBlock(
|
||||
ctx,
|
||||
in1.(*PushBlockRequest),
|
||||
)
|
||||
}, DRPCFileServer.PushBlock, true
|
||||
case 2:
|
||||
return "/anySpace.File/DeleteBlocks", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCFileServer).
|
||||
DeleteBlocks(
|
||||
ctx,
|
||||
in1.(*DeleteBlocksRequest),
|
||||
)
|
||||
}, DRPCFileServer.DeleteBlocks, true
|
||||
case 3:
|
||||
return "/anySpace.File/Check", drpcEncoding_File_commonfile_fileproto_protos_file_proto{},
|
||||
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
|
||||
return srv.(DRPCFileServer).
|
||||
Check(
|
||||
ctx,
|
||||
in1.(*CheckRequest),
|
||||
)
|
||||
}, DRPCFileServer.Check, true
|
||||
default:
|
||||
return "", nil, nil, nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func DRPCRegisterFile(mux drpc.Mux, impl DRPCFileServer) error {
|
||||
return mux.Register(impl, DRPCFileDescription{})
|
||||
}
|
||||
|
||||
type DRPCFile_GetBlocksStream interface {
|
||||
drpc.Stream
|
||||
Send(*GetBlockResponse) error
|
||||
Recv() (*GetBlockRequest, error)
|
||||
}
|
||||
|
||||
type drpcFile_GetBlocksStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksStream) Send(m *GetBlockResponse) error {
|
||||
return x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksStream) Recv() (*GetBlockRequest, error) {
|
||||
m := new(GetBlockRequest)
|
||||
if err := x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (x *drpcFile_GetBlocksStream) RecvMsg(m *GetBlockRequest) error {
|
||||
return x.MsgRecv(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{})
|
||||
}
|
||||
|
||||
type DRPCFile_PushBlockStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*PushBlockResponse) error
|
||||
}
|
||||
|
||||
type drpcFile_PushBlockStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcFile_PushBlockStream) SendAndClose(m *PushBlockResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCFile_DeleteBlocksStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*DeleteBlocksResponse) error
|
||||
}
|
||||
|
||||
type drpcFile_DeleteBlocksStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcFile_DeleteBlocksStream) SendAndClose(m *DeleteBlocksResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
||||
|
||||
type DRPCFile_CheckStream interface {
|
||||
drpc.Stream
|
||||
SendAndClose(*CheckResponse) error
|
||||
}
|
||||
|
||||
type drpcFile_CheckStream struct {
|
||||
drpc.Stream
|
||||
}
|
||||
|
||||
func (x *drpcFile_CheckStream) SendAndClose(m *CheckResponse) error {
|
||||
if err := x.MsgSend(m, drpcEncoding_File_commonfile_fileproto_protos_file_proto{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return x.CloseSend()
|
||||
}
|
60
common/commonfile/fileproto/protos/file.proto
Normal file
60
common/commonfile/fileproto/protos/file.proto
Normal file
|
@ -0,0 +1,60 @@
|
|||
syntax = "proto3";
|
||||
package anySpace;
|
||||
|
||||
option go_package = "commonfile/fileproto";
|
||||
|
||||
enum ErrCodes {
|
||||
Unexpected = 0;
|
||||
CIDNotFound = 1;
|
||||
ErrorOffset = 200;
|
||||
}
|
||||
|
||||
service File {
|
||||
// GetBlocks streams ipfs blocks from server to client
|
||||
rpc GetBlocks(stream GetBlockRequest) returns (stream GetBlockResponse);
|
||||
// PushBlock pushes one block to server
|
||||
rpc PushBlock(PushBlockRequest) returns (PushBlockResponse);
|
||||
// DeleteBlock deletes block from space
|
||||
rpc DeleteBlocks(DeleteBlocksRequest) returns (DeleteBlocksResponse);
|
||||
// Ping checks the connection
|
||||
rpc Check(CheckRequest) returns (CheckResponse);
|
||||
}
|
||||
|
||||
message GetBlockRequest {
|
||||
string spaceId = 1;
|
||||
bytes cid = 2;
|
||||
}
|
||||
|
||||
message GetBlockResponse {
|
||||
bytes cid = 1;
|
||||
bytes data = 2;
|
||||
CIDError code = 3;
|
||||
}
|
||||
|
||||
message PushBlockRequest {
|
||||
string spaceId = 1;
|
||||
bytes cid = 2;
|
||||
bytes data = 3;
|
||||
}
|
||||
|
||||
message PushBlockResponse {}
|
||||
|
||||
message DeleteBlocksRequest {
|
||||
string spaceId = 1;
|
||||
repeated bytes cid = 2;
|
||||
}
|
||||
|
||||
message DeleteBlocksResponse {}
|
||||
|
||||
message CheckRequest {}
|
||||
|
||||
message CheckResponse {
|
||||
repeated string spaceIds = 1;
|
||||
}
|
||||
|
||||
|
||||
enum CIDError {
|
||||
CIDErrorOk = 0;
|
||||
CIDErrorNotFound = 1;
|
||||
CIDErrorUnexpected = 2;
|
||||
}
|
|
@ -8,8 +8,13 @@ import (
|
|||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type IPFSStoreExistsCIDs interface {
|
||||
IPFSStore
|
||||
ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error)
|
||||
}
|
||||
|
||||
type CacheStore struct {
|
||||
Cache IPFSStore
|
||||
Cache IPFSStoreExistsCIDs
|
||||
Origin IPFSStore
|
||||
}
|
||||
|
||||
|
@ -90,10 +95,6 @@ func (c *CacheStore) GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Bl
|
|||
return results
|
||||
}
|
||||
|
||||
func (c *CacheStore) ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error) {
|
||||
return c.Cache.ExistsCids(ctx, ks)
|
||||
}
|
||||
|
||||
func (c *CacheStore) Add(ctx context.Context, b []blocks.Block) error {
|
||||
if localErr := c.Cache.Add(ctx, b); localErr != nil {
|
||||
log.Error("cache add error", zap.Error(localErr))
|
||||
|
|
|
@ -12,7 +12,6 @@ var log = logger.NewNamed("filenode.ipfsstore")
|
|||
type IPFSStore interface {
|
||||
Get(ctx context.Context, k cid.Cid) (blocks.Block, error)
|
||||
GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Block
|
||||
ExistsCids(ctx context.Context, ks []cid.Cid) (exists []cid.Cid, err error)
|
||||
Add(ctx context.Context, b []blocks.Block) error
|
||||
Delete(ctx context.Context, c cid.Cid) error
|
||||
Close() (err error)
|
||||
|
|
275
common/commonfile/rpcstore/client.go
Normal file
275
common/commonfile/rpcstore/client.go
Normal file
|
@ -0,0 +1,275 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/fileproto"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/slice"
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"github.com/ipfs/go-cid"
|
||||
"go.uber.org/zap"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCIDNotFound = errors.New("CID not found")
|
||||
ErrCIDUnexpected = errors.New("CID unexpected error")
|
||||
ErrClientClosed = errors.New("file client closed")
|
||||
)
|
||||
|
||||
const defaultMaxInFlightCIDs = 10
|
||||
|
||||
func newClient(ctx context.Context, s *service, peerId string, tq *mb.MB[*task]) (*client, error) {
|
||||
c := &client{
|
||||
peerId: peerId,
|
||||
taskQueue: tq,
|
||||
waitCIDs: map[string]*task{},
|
||||
waitCIDCap: make(chan struct{}, defaultMaxInFlightCIDs),
|
||||
opLoopDone: make(chan struct{}),
|
||||
stat: newStat(),
|
||||
s: s,
|
||||
}
|
||||
if err := c.checkConnectivity(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var runCtx context.Context
|
||||
runCtx, c.opLoopCtxCancel = context.WithCancel(context.Background())
|
||||
go c.opLoop(runCtx)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// client gets and executes tasks from taskQueue
|
||||
// it has an internal queue for a waiting CIDs
|
||||
type client struct {
|
||||
peerId string
|
||||
spaceIds []string
|
||||
taskQueue *mb.MB[*task]
|
||||
blocksStream fileproto.DRPCFile_GetBlocksClient
|
||||
blocksStreamMu sync.Mutex
|
||||
waitCIDs map[string]*task
|
||||
waitCIDCap chan struct{}
|
||||
waitCIDMu sync.Mutex
|
||||
opLoopDone chan struct{}
|
||||
opLoopCtxCancel context.CancelFunc
|
||||
stat *stat
|
||||
s *service
|
||||
}
|
||||
|
||||
// opLoop gets tasks from taskQueue
|
||||
func (c *client) opLoop(ctx context.Context) {
|
||||
defer close(c.opLoopDone)
|
||||
c.waitCIDMu.Lock()
|
||||
spaceIds := c.spaceIds
|
||||
c.waitCIDMu.Unlock()
|
||||
cond := c.taskQueue.NewCond().WithFilter(func(t *task) bool {
|
||||
if slice.FindPos(t.denyPeerIds, c.peerId) != -1 {
|
||||
return false
|
||||
}
|
||||
if len(spaceIds) > 0 && slice.FindPos(spaceIds, t.spaceId) == -1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
for {
|
||||
t, err := cond.WithPriority(c.stat.Score()).WaitOne(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
t.peerId = c.peerId
|
||||
switch t.op {
|
||||
case taskOpGet:
|
||||
err = c.get(ctx, t)
|
||||
case taskOpDelete:
|
||||
err = c.delete(ctx, t)
|
||||
case taskOpPut:
|
||||
err = c.put(ctx, t)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected task op type: %v", t.op)
|
||||
}
|
||||
if err != nil {
|
||||
t.err = err
|
||||
t.ready <- t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) delete(ctx context.Context, t *task) (err error) {
|
||||
p, err := c.s.pool.Get(ctx, c.peerId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = fileproto.NewDRPCFileClient(p).DeleteBlocks(ctx, &fileproto.DeleteBlocksRequest{
|
||||
SpaceId: t.spaceId,
|
||||
Cid: [][]byte{t.cid.Bytes()},
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
t.ready <- t
|
||||
c.stat.UpdateLastUsage()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *client) put(ctx context.Context, t *task) (err error) {
|
||||
p, err := c.s.pool.Get(ctx, c.peerId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
st := time.Now()
|
||||
if _, err = fileproto.NewDRPCFileClient(p).PushBlock(ctx, &fileproto.PushBlockRequest{
|
||||
SpaceId: t.spaceId,
|
||||
Cid: t.cid.Bytes(),
|
||||
Data: t.data,
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
t.ready <- t
|
||||
c.stat.Add(st, len(t.data))
|
||||
return
|
||||
}
|
||||
|
||||
// get sends the get request to the stream and adds task to waiting list
|
||||
func (c *client) get(ctx context.Context, t *task) (err error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case c.waitCIDCap <- struct{}{}:
|
||||
}
|
||||
c.waitCIDMu.Lock()
|
||||
t.startTime = time.Now()
|
||||
c.waitCIDs[t.cid.String()] = t
|
||||
c.waitCIDMu.Unlock()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
c.waitCIDMu.Lock()
|
||||
delete(c.waitCIDs, t.cid.String())
|
||||
c.waitCIDMu.Unlock()
|
||||
<-c.waitCIDCap
|
||||
}
|
||||
}()
|
||||
|
||||
bs, err := c.getStream(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = bs.Send(&fileproto.GetBlockRequest{
|
||||
SpaceId: t.spaceId,
|
||||
Cid: t.cid.Bytes(),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *client) readStream() {
|
||||
var err error
|
||||
defer func() {
|
||||
log.Info("readStream closed", zap.String("peerId", c.peerId), zap.Error(err))
|
||||
c.waitCIDMu.Lock()
|
||||
c.blocksStream = nil
|
||||
c.waitCIDMu.Unlock()
|
||||
}()
|
||||
for {
|
||||
var resp *fileproto.GetBlockResponse
|
||||
resp, err = c.blocksStream.Recv()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var t *task
|
||||
t, err = c.receiveCID(resp)
|
||||
if err != nil {
|
||||
log.Warn("cid receive error", zap.Error(err))
|
||||
} else {
|
||||
t.ready <- t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// receiveCID handles stream response, finds cid in waiting list and sets data to task
|
||||
func (c *client) receiveCID(resp *fileproto.GetBlockResponse) (t *task, err error) {
|
||||
_, rCid, err := cid.CidFromBytes(resp.Cid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("got invalid CID from node: %v", err)
|
||||
}
|
||||
c.waitCIDMu.Lock()
|
||||
defer c.waitCIDMu.Unlock()
|
||||
t, ok := c.waitCIDs[rCid.String()]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("got unexpected CID from node: %v", rCid.String())
|
||||
}
|
||||
switch resp.Code {
|
||||
case fileproto.CIDError_CIDErrorOk:
|
||||
t.data = resp.Data
|
||||
t.err = nil
|
||||
case fileproto.CIDError_CIDErrorNotFound:
|
||||
t.err = ErrCIDNotFound
|
||||
default:
|
||||
t.err = ErrCIDUnexpected
|
||||
}
|
||||
delete(c.waitCIDs, rCid.String())
|
||||
if t.err == nil {
|
||||
c.stat.Add(t.startTime, len(t.data))
|
||||
}
|
||||
<-c.waitCIDCap
|
||||
return
|
||||
}
|
||||
|
||||
func (c *client) getStream(ctx context.Context) (fileproto.DRPCFile_GetBlocksClient, error) {
|
||||
c.blocksStreamMu.Lock()
|
||||
defer c.blocksStreamMu.Unlock()
|
||||
if c.blocksStream != nil {
|
||||
return c.blocksStream, nil
|
||||
}
|
||||
peer, err := c.s.pool.Dial(ctx, c.peerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.blocksStream, err = fileproto.NewDRPCFileClient(peer).GetBlocks(context.Background()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go c.readStream()
|
||||
return c.blocksStream, nil
|
||||
}
|
||||
|
||||
func (c *client) checkConnectivity(ctx context.Context) (err error) {
|
||||
p, err := c.s.pool.Get(ctx, c.peerId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := fileproto.NewDRPCFileClient(p).Check(ctx, &fileproto.CheckRequest{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.waitCIDMu.Lock()
|
||||
defer c.waitCIDMu.Unlock()
|
||||
c.spaceIds = resp.SpaceIds
|
||||
return
|
||||
}
|
||||
|
||||
func (c *client) LastUsage() time.Time {
|
||||
return c.stat.LastUsage()
|
||||
}
|
||||
|
||||
func (c *client) Close() error {
|
||||
// stop receiving tasks
|
||||
c.opLoopCtxCancel()
|
||||
<-c.opLoopDone
|
||||
c.blocksStreamMu.Lock()
|
||||
// close stream
|
||||
if c.blocksStream != nil {
|
||||
_ = c.blocksStream.CloseSend()
|
||||
c.blocksStream = nil
|
||||
}
|
||||
c.blocksStreamMu.Unlock()
|
||||
// cleanup waiting list
|
||||
c.waitCIDMu.Lock()
|
||||
for id, t := range c.waitCIDs {
|
||||
t.err = ErrClientClosed
|
||||
t.ready <- t
|
||||
delete(c.waitCIDs, id)
|
||||
}
|
||||
c.waitCIDMu.Unlock()
|
||||
return nil
|
||||
}
|
110
common/commonfile/rpcstore/clientmgr.go
Normal file
110
common/commonfile/rpcstore/clientmgr.go
Normal file
|
@ -0,0 +1,110 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"go.uber.org/zap"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
maxConnections = 10
|
||||
maxTasks = 1000
|
||||
)
|
||||
|
||||
var (
|
||||
clientCreateTimeout = time.Second * 10
|
||||
)
|
||||
|
||||
func newClientManager(s *service) *clientManager {
|
||||
cm := &clientManager{
|
||||
mb: mb.New[*task](maxTasks),
|
||||
ocache: ocache.New(
|
||||
func(ctx context.Context, id string) (value ocache.Object, err error) {
|
||||
return nil, fmt.Errorf("load func shouldn't be used")
|
||||
},
|
||||
ocache.WithTTL(time.Minute*5),
|
||||
ocache.WithRefCounter(false),
|
||||
ocache.WithLogger(log.Sugar()),
|
||||
ocache.WithGCPeriod(0),
|
||||
),
|
||||
s: s,
|
||||
}
|
||||
cm.ctx, cm.ctxCancel = context.WithCancel(context.Background())
|
||||
go cm.checkPeerLoop()
|
||||
return cm
|
||||
}
|
||||
|
||||
// clientManager manages clients, removes unused ones, and adds new ones if necessary
|
||||
type clientManager struct {
|
||||
mb *mb.MB[*task]
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
ocache ocache.OCache
|
||||
|
||||
s *service
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func (m *clientManager) Add(ctx context.Context, ts ...*task) (err error) {
|
||||
return m.mb.Add(ctx, ts...)
|
||||
}
|
||||
|
||||
func (m *clientManager) checkPeerLoop() {
|
||||
m.checkPeers()
|
||||
ticker := time.NewTicker(time.Minute)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-m.ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
m.checkPeers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *clientManager) checkPeers() {
|
||||
// start GC to remove unused clients
|
||||
m.ocache.GC()
|
||||
if m.ocache.Len() >= maxConnections {
|
||||
// reached connection limit, can't add new peers
|
||||
return
|
||||
}
|
||||
if m.ocache.Len() != 0 && m.mb.Len() == 0 {
|
||||
// has empty queue, no need new peers
|
||||
return
|
||||
}
|
||||
|
||||
// try to add new peers
|
||||
peerIds := m.s.filePeers()
|
||||
rand.Shuffle(len(peerIds), func(i, j int) {
|
||||
peerIds[i], peerIds[j] = peerIds[j], peerIds[i]
|
||||
})
|
||||
for _, peerId := range peerIds {
|
||||
if _, cerr := m.ocache.Pick(m.ctx, peerId); cerr == ocache.ErrNotExists {
|
||||
ctx, cancel := context.WithTimeout(m.ctx, clientCreateTimeout)
|
||||
cl, err := newClient(ctx, m.s, peerId, m.mb)
|
||||
if err != nil {
|
||||
log.Info("can't create client", zap.Error(err))
|
||||
cancel()
|
||||
continue
|
||||
}
|
||||
_ = m.ocache.Add(peerId, cl)
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *clientManager) Close() (err error) {
|
||||
m.ctxCancel()
|
||||
if err = m.mb.Close(); err != nil {
|
||||
log.Error("mb close error", zap.Error(err))
|
||||
}
|
||||
return m.ocache.Close()
|
||||
}
|
49
common/commonfile/rpcstore/service.go
Normal file
49
common/commonfile/rpcstore/service.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/ipfsstore"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||
)
|
||||
|
||||
const CName = "common.commonfile.rpcstore"
|
||||
|
||||
var log = logger.NewNamed(CName)
|
||||
|
||||
func New() Service {
|
||||
return &service{}
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
NewStore() ipfsstore.IPFSStore
|
||||
app.Component
|
||||
}
|
||||
|
||||
type service struct {
|
||||
pool pool.Pool
|
||||
nodeconf nodeconf.Service
|
||||
}
|
||||
|
||||
func (s *service) Init(a *app.App) (err error) {
|
||||
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
||||
s.nodeconf = a.MustComponent(nodeconf.CName).(nodeconf.Service)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *service) Name() (name string) {
|
||||
return CName
|
||||
}
|
||||
|
||||
func (s *service) NewStore() ipfsstore.IPFSStore {
|
||||
cm := newClientManager(s)
|
||||
return &store{
|
||||
s: s,
|
||||
cm: cm,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) filePeers() []string {
|
||||
return s.nodeconf.GetLast().FilePeers()
|
||||
}
|
55
common/commonfile/rpcstore/stat.go
Normal file
55
common/commonfile/rpcstore/stat.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"github.com/VividCortex/ewma"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// defaultSpeedScore - initial value in Kb/s, it should be relatively high to test fresh client soon
|
||||
const defaultSpeedScore = 10 * 1024
|
||||
|
||||
func newStat() *stat {
|
||||
s := &stat{
|
||||
ewma: &ewma.SimpleEWMA{},
|
||||
lastUsage: time.Now(),
|
||||
}
|
||||
s.ewma.Set(float64(defaultSpeedScore))
|
||||
return s
|
||||
}
|
||||
|
||||
// stat calculates EWMA download/upload speed
|
||||
type stat struct {
|
||||
// TODO: rewrite to atomics
|
||||
ewma *ewma.SimpleEWMA
|
||||
mu sync.Mutex
|
||||
lastUsage time.Time
|
||||
}
|
||||
|
||||
// Score returns average download/upload speed in Kb/s
|
||||
func (s *stat) Score() float64 {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.ewma.Value()
|
||||
}
|
||||
|
||||
// Add adds new sample to the stat
|
||||
func (s *stat) Add(startTime time.Time, byteLen int) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
dur := time.Since(startTime).Seconds()
|
||||
s.ewma.Add(float64(byteLen) / 1024 / dur)
|
||||
s.lastUsage = time.Now()
|
||||
}
|
||||
|
||||
func (s *stat) LastUsage() time.Time {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return s.lastUsage
|
||||
}
|
||||
|
||||
func (s *stat) UpdateLastUsage() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.lastUsage = time.Now()
|
||||
}
|
99
common/commonfile/rpcstore/store.go
Normal file
99
common/commonfile/rpcstore/store.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var closedBlockChan chan blocks.Block
|
||||
|
||||
func init() {
|
||||
closedBlockChan = make(chan blocks.Block)
|
||||
close(closedBlockChan)
|
||||
}
|
||||
|
||||
type store struct {
|
||||
s *service
|
||||
cm *clientManager
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
func (s *store) Get(ctx context.Context, k cid.Cid) (b blocks.Block, err error) {
|
||||
t := newTask(ctx, taskOpGet, k, nil)
|
||||
if err = s.cm.Add(ctx, t); err != nil {
|
||||
return
|
||||
}
|
||||
<-t.ready
|
||||
if err = t.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
return t.Block()
|
||||
}
|
||||
|
||||
func (s *store) GetMany(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
|
||||
var readyCh = make(chan *task)
|
||||
var tasks = make([]*task, len(ks))
|
||||
for i, k := range ks {
|
||||
tasks[i] = newTask(ctx, taskOpGet, k, readyCh)
|
||||
}
|
||||
if err := s.cm.Add(ctx, tasks...); err != nil {
|
||||
log.Error("getMany: can't add tasks", zap.Error(err))
|
||||
return closedBlockChan
|
||||
}
|
||||
var result = make(chan blocks.Block)
|
||||
go func() {
|
||||
defer close(result)
|
||||
for i := 0; i < len(tasks); i++ {
|
||||
var t *task
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case t = <-readyCh:
|
||||
}
|
||||
if err := t.Validate(); err != nil {
|
||||
// TODO: fallback
|
||||
log.Warn("received not valid block", zap.Error(err))
|
||||
}
|
||||
b, _ := t.Block()
|
||||
result <- b
|
||||
}
|
||||
}()
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *store) Add(ctx context.Context, bs []blocks.Block) error {
|
||||
var readyCh = make(chan *task)
|
||||
var tasks = make([]*task, len(bs))
|
||||
for i, b := range bs {
|
||||
tasks[i] = newTask(ctx, taskOpPut, b.Cid(), readyCh)
|
||||
tasks[i].data = b.RawData()
|
||||
}
|
||||
if err := s.cm.Add(ctx, tasks...); err != nil {
|
||||
return err
|
||||
}
|
||||
var errs []error
|
||||
for i := 0; i < len(tasks); i++ {
|
||||
t := <-readyCh
|
||||
if t.err != nil {
|
||||
errs = append(errs, t.err)
|
||||
}
|
||||
}
|
||||
return multierr.Combine(errs...)
|
||||
}
|
||||
|
||||
func (s *store) Delete(ctx context.Context, c cid.Cid) error {
|
||||
t := newTask(ctx, taskOpDelete, c, nil)
|
||||
if err := s.cm.Add(ctx, t); err != nil {
|
||||
return err
|
||||
}
|
||||
<-t.ready
|
||||
return t.err
|
||||
}
|
||||
|
||||
func (s *store) Close() (err error) {
|
||||
return s.cm.Close()
|
||||
}
|
190
common/commonfile/rpcstore/store_test.go
Normal file
190
common/commonfile/rpcstore/store_test.go
Normal file
|
@ -0,0 +1,190 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/fileproto"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
func TestStore_Put(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.Finish(t)
|
||||
|
||||
bs := []blocks.Block{
|
||||
blocks.NewBlock([]byte{'1'}),
|
||||
blocks.NewBlock([]byte{'2'}),
|
||||
blocks.NewBlock([]byte{'3'}),
|
||||
}
|
||||
err := fx.Add(ctx, bs)
|
||||
assert.NoError(t, err)
|
||||
for _, b := range bs {
|
||||
assert.NotNil(t, fx.serv.data[string(b.Cid().Bytes())])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStore_Delete(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.Finish(t)
|
||||
bs := []blocks.Block{
|
||||
blocks.NewBlock([]byte{'1'}),
|
||||
}
|
||||
err := fx.Add(ctx, bs)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, fx.serv.data, 1)
|
||||
require.NoError(t, fx.Delete(ctx, bs[0].Cid()))
|
||||
assert.Len(t, fx.serv.data, 0)
|
||||
}
|
||||
|
||||
func TestStore_Get(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.Finish(t)
|
||||
bs := []blocks.Block{
|
||||
blocks.NewBlock([]byte{'1'}),
|
||||
}
|
||||
err := fx.Add(ctx, bs)
|
||||
require.NoError(t, err)
|
||||
b, err := fx.Get(ctx, bs[0].Cid())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte{'1'}, b.RawData())
|
||||
})
|
||||
t.Run("not found", func(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.Finish(t)
|
||||
bs := []blocks.Block{
|
||||
blocks.NewBlock([]byte{'1'}),
|
||||
}
|
||||
b, err := fx.Get(ctx, bs[0].Cid())
|
||||
assert.Nil(t, b)
|
||||
assert.ErrorIs(t, err, ErrCIDNotFound)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStore_GetMany(t *testing.T) {
|
||||
fx := newFixture(t)
|
||||
defer fx.Finish(t)
|
||||
|
||||
bs := []blocks.Block{
|
||||
blocks.NewBlock([]byte{'1'}),
|
||||
blocks.NewBlock([]byte{'2'}),
|
||||
blocks.NewBlock([]byte{'3'}),
|
||||
}
|
||||
err := fx.Add(ctx, bs)
|
||||
assert.NoError(t, err)
|
||||
|
||||
res := fx.GetMany(ctx, []cid.Cid{
|
||||
bs[0].Cid(),
|
||||
bs[1].Cid(),
|
||||
bs[2].Cid(),
|
||||
})
|
||||
var resBlocks []blocks.Block
|
||||
for b := range res {
|
||||
resBlocks = append(resBlocks, b)
|
||||
}
|
||||
require.Len(t, resBlocks, 3)
|
||||
sort.Slice(resBlocks, func(i, j int) bool {
|
||||
return string(resBlocks[i].RawData()) < string(resBlocks[j].RawData())
|
||||
})
|
||||
assert.Equal(t, bs, resBlocks)
|
||||
}
|
||||
|
||||
func newFixture(t *testing.T) *fixture {
|
||||
fx := &fixture{
|
||||
a: new(app.App),
|
||||
s: New().(*service),
|
||||
serv: &testServer{
|
||||
data: make(map[string][]byte),
|
||||
},
|
||||
}
|
||||
|
||||
conf := &config.Config{}
|
||||
|
||||
for i := 0; i < 11; i++ {
|
||||
conf.Nodes = append(conf.Nodes, config.Node{
|
||||
PeerId: fmt.Sprint(i),
|
||||
Types: []config.NodeType{config.NodeTypeFile},
|
||||
})
|
||||
}
|
||||
rserv := rpctest.NewTestServer()
|
||||
require.NoError(t, fileproto.DRPCRegisterFile(rserv.Mux, fx.serv))
|
||||
fx.a.Register(fx.s).
|
||||
Register(rpctest.NewTestPool().WithServer(rserv)).
|
||||
Register(nodeconf.New()).
|
||||
Register(conf)
|
||||
require.NoError(t, fx.a.Start(ctx))
|
||||
fx.store = fx.s.NewStore().(*store)
|
||||
return fx
|
||||
}
|
||||
|
||||
type fixture struct {
|
||||
*store
|
||||
s *service
|
||||
a *app.App
|
||||
serv *testServer
|
||||
}
|
||||
|
||||
func (fx *fixture) Finish(t *testing.T) {
|
||||
assert.NoError(t, fx.store.Close())
|
||||
assert.NoError(t, fx.a.Close(ctx))
|
||||
}
|
||||
|
||||
type testServer struct {
|
||||
mu sync.Mutex
|
||||
data map[string][]byte
|
||||
}
|
||||
|
||||
func (t *testServer) GetBlocks(stream fileproto.DRPCFile_GetBlocksStream) error {
|
||||
for {
|
||||
req, err := stream.Recv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.mu.Lock()
|
||||
resp := &fileproto.GetBlockResponse{
|
||||
Cid: req.Cid,
|
||||
}
|
||||
if data, ok := t.data[string(req.Cid)]; ok {
|
||||
resp.Data = data
|
||||
} else {
|
||||
resp.Code = fileproto.CIDError_CIDErrorNotFound
|
||||
}
|
||||
t.mu.Unlock()
|
||||
if err = stream.Send(resp); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *testServer) PushBlock(ctx context.Context, req *fileproto.PushBlockRequest) (*fileproto.PushBlockResponse, error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
t.data[string(req.Cid)] = req.Data
|
||||
return &fileproto.PushBlockResponse{}, nil
|
||||
}
|
||||
|
||||
func (t *testServer) DeleteBlocks(ctx context.Context, req *fileproto.DeleteBlocksRequest) (*fileproto.DeleteBlocksResponse, error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
for _, c := range req.Cid {
|
||||
delete(t.data, string(c))
|
||||
}
|
||||
return &fileproto.DeleteBlocksResponse{}, nil
|
||||
}
|
||||
|
||||
func (t *testServer) Check(ctx context.Context, req *fileproto.CheckRequest) (*fileproto.CheckResponse, error) {
|
||||
return &fileproto.CheckResponse{}, nil
|
||||
}
|
60
common/commonfile/rpcstore/task.go
Normal file
60
common/commonfile/rpcstore/task.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package rpcstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type taskOp uint
|
||||
|
||||
const (
|
||||
taskOpGet taskOp = iota
|
||||
taskOpPut
|
||||
taskOpDelete
|
||||
)
|
||||
|
||||
func newTask(ctx context.Context, op taskOp, c cid.Cid, readyCh chan *task) *task {
|
||||
t := &task{
|
||||
cid: c,
|
||||
ctx: ctx,
|
||||
ready: readyCh,
|
||||
op: op,
|
||||
}
|
||||
if t.ready == nil {
|
||||
t.ready = make(chan *task)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
type task struct {
|
||||
op taskOp
|
||||
ctx context.Context
|
||||
cid cid.Cid
|
||||
data []byte
|
||||
peerId string
|
||||
spaceId string
|
||||
denyPeerIds []string
|
||||
ready chan *task
|
||||
startTime time.Time
|
||||
err error
|
||||
}
|
||||
|
||||
func (t *task) Validate() error {
|
||||
if t.err != nil {
|
||||
return t.err
|
||||
}
|
||||
chkc, err := t.cid.Prefix().Sum(t.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !chkc.Equals(t.cid) {
|
||||
return blocks.ErrWrongHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *task) Block() (blocks.Block, error) {
|
||||
return blocks.NewBlockWithCid(t.data, t.cid)
|
||||
}
|
|
@ -1,9 +1,26 @@
|
|||
package config
|
||||
|
||||
type NodeType string
|
||||
|
||||
const (
|
||||
NodeTypeTree NodeType = "tree"
|
||||
NodeTypeConsensus NodeType = "consensus"
|
||||
NodeTypeFile NodeType = "file"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
PeerId string `yaml:"peerId"`
|
||||
Address string `yaml:"address"`
|
||||
SigningKey string `yaml:"signingKey,omitempty"`
|
||||
EncryptionKey string `yaml:"encryptionKey,omitempty"`
|
||||
IsConsensus bool `yaml:"isConsensus,omitempty"`
|
||||
PeerId string `yaml:"peerId"`
|
||||
Address string `yaml:"address"`
|
||||
SigningKey string `yaml:"signingKey,omitempty"`
|
||||
EncryptionKey string `yaml:"encryptionKey,omitempty"`
|
||||
Types []NodeType `yaml:"types,omitempty"`
|
||||
}
|
||||
|
||||
func (n Node) HasType(t NodeType) bool {
|
||||
for _, nt := range n.Types {
|
||||
if nt == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -29,8 +29,11 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cheggaaa/mb/v2 v2.1.0-alpha // indirect
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/fogleman/gg v1.3.0 // indirect
|
||||
|
|
|
@ -35,6 +35,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
|
@ -58,6 +60,14 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
|
|||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheggaaa/mb/v2 v2.1.0-alpha h1:GN2R1eUrImfd8lwmx6VfX6E4RqXoOjUBdZLo9aqw87o=
|
||||
github.com/cheggaaa/mb/v2 v2.1.0-alpha/go.mod h1:XGeZw20Iqgjky26KL0mvCwk3+4NyZCUbshSo6ALne+c=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221116073802-28877f0c7d6c h1:qgBgvJEmHz9Jhe2Aso0y1djx9RpQo6AiC1k1ScCyQTc=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221116073802-28877f0c7d6c/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221116093702-e509afb93b07 h1:iApZflWEqUGURwq88cOgAA5+I686xFabUj4YvPCKfUo=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221116093702-e509afb93b07/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c h1:+bD75daSbsxyTzkKpNplC4xls+7/tGwty+zruzOnOmk=
|
||||
github.com/cheggaaa/mb/v3 v3.0.0-20221122160120-e9034545510c/go.mod h1:zCt2QeYukhd/g0bIdNqF+b/kKz1hnLFNDkP49qN5kqI=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
|
|
|
@ -5,10 +5,6 @@ import (
|
|||
"github.com/anytypeio/go-chash"
|
||||
)
|
||||
|
||||
func New() Service {
|
||||
return new(service)
|
||||
}
|
||||
|
||||
type Configuration interface {
|
||||
// Id returns current nodeconf id
|
||||
Id() string
|
||||
|
@ -16,12 +12,18 @@ type Configuration interface {
|
|||
NodeIds(spaceId string) []string
|
||||
// IsResponsible checks if current account responsible for given spaceId
|
||||
IsResponsible(spaceId string) bool
|
||||
// FilePeers returns list of filenodes
|
||||
FilePeers() []string
|
||||
// ConsensusPeers returns list of consensusnodes
|
||||
ConsensusPeers() []string
|
||||
}
|
||||
|
||||
type configuration struct {
|
||||
id string
|
||||
accountId string
|
||||
chash chash.CHash
|
||||
id string
|
||||
accountId string
|
||||
filePeers []string
|
||||
consensusPeers []string
|
||||
chash chash.CHash
|
||||
}
|
||||
|
||||
func (c *configuration) Id() string {
|
||||
|
@ -47,3 +49,11 @@ func (c *configuration) IsResponsible(spaceId string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *configuration) FilePeers() []string {
|
||||
return c.filePeers
|
||||
}
|
||||
|
||||
func (c *configuration) ConsensusPeers() []string {
|
||||
return c.consensusPeers
|
||||
}
|
||||
|
|
|
@ -37,20 +37,6 @@ func (m *MockService) EXPECT() *MockServiceMockRecorder {
|
|||
return m.recorder
|
||||
}
|
||||
|
||||
// ConsensusPeers mocks base method.
|
||||
func (m *MockService) ConsensusPeers() []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ConsensusPeers")
|
||||
ret0, _ := ret[0].([]string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ConsensusPeers indicates an expected call of ConsensusPeers.
|
||||
func (mr *MockServiceMockRecorder) ConsensusPeers() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusPeers", reflect.TypeOf((*MockService)(nil).ConsensusPeers))
|
||||
}
|
||||
|
||||
// GetById mocks base method.
|
||||
func (m *MockService) GetById(arg0 string) nodeconf.Configuration {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -130,6 +116,34 @@ func (m *MockConfiguration) EXPECT() *MockConfigurationMockRecorder {
|
|||
return m.recorder
|
||||
}
|
||||
|
||||
// ConsensusPeers mocks base method.
|
||||
func (m *MockConfiguration) ConsensusPeers() []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ConsensusPeers")
|
||||
ret0, _ := ret[0].([]string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ConsensusPeers indicates an expected call of ConsensusPeers.
|
||||
func (mr *MockConfigurationMockRecorder) ConsensusPeers() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusPeers", reflect.TypeOf((*MockConfiguration)(nil).ConsensusPeers))
|
||||
}
|
||||
|
||||
// FilePeers mocks base method.
|
||||
func (m *MockConfiguration) FilePeers() []string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FilePeers")
|
||||
ret0, _ := ret[0].([]string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// FilePeers indicates an expected call of FilePeers.
|
||||
func (mr *MockConfigurationMockRecorder) FilePeers() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilePeers", reflect.TypeOf((*MockConfiguration)(nil).FilePeers))
|
||||
}
|
||||
|
||||
// Id mocks base method.
|
||||
func (m *MockConfiguration) Id() string {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
@ -19,18 +19,19 @@ const (
|
|||
|
||||
var log = logger.NewNamed(CName)
|
||||
|
||||
func New() Service {
|
||||
return new(service)
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
GetLast() Configuration
|
||||
GetById(id string) Configuration
|
||||
ConsensusPeers() []string
|
||||
app.Component
|
||||
}
|
||||
|
||||
type service struct {
|
||||
accountId string
|
||||
|
||||
consensusPeers []string
|
||||
last Configuration
|
||||
last Configuration
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
|
@ -52,11 +53,11 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
conf := a.MustComponent(config.CName).(*config.Config)
|
||||
s.accountId = conf.Account.PeerId
|
||||
|
||||
config := &configuration{
|
||||
fileConfig := &configuration{
|
||||
id: "config",
|
||||
accountId: s.accountId,
|
||||
}
|
||||
if config.chash, err = chash.New(chash.Config{
|
||||
if fileConfig.chash, err = chash.New(chash.Config{
|
||||
PartitionCount: partitionCount,
|
||||
ReplicationFactor: replicationFactor,
|
||||
}); err != nil {
|
||||
|
@ -64,21 +65,28 @@ func (s *service) Init(a *app.App) (err error) {
|
|||
}
|
||||
members := make([]chash.Member, 0, len(conf.Nodes))
|
||||
for _, n := range conf.Nodes {
|
||||
if n.IsConsensus {
|
||||
s.consensusPeers = append(s.consensusPeers, n.PeerId)
|
||||
if n.HasType(config.NodeTypeTree) {
|
||||
var member *Node
|
||||
member, err = nodeFromConfigNode(n)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
members = append(members, member)
|
||||
}
|
||||
if n.PeerId == s.accountId {
|
||||
continue
|
||||
}
|
||||
var member *Node
|
||||
member, err = nodeFromConfigNode(n)
|
||||
if err != nil {
|
||||
return
|
||||
if n.HasType(config.NodeTypeConsensus) {
|
||||
fileConfig.consensusPeers = append(fileConfig.consensusPeers, n.PeerId)
|
||||
}
|
||||
if n.HasType(config.NodeTypeFile) {
|
||||
fileConfig.filePeers = append(fileConfig.filePeers, n.PeerId)
|
||||
}
|
||||
members = append(members, member)
|
||||
}
|
||||
if err = config.chash.AddMembers(members...); err != nil {
|
||||
if err = fileConfig.chash.AddMembers(members...); err != nil {
|
||||
return
|
||||
}
|
||||
s.last = config
|
||||
s.last = fileConfig
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -95,10 +103,6 @@ func (s *service) GetById(id string) Configuration {
|
|||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *service) ConsensusPeers() []string {
|
||||
return s.consensusPeers
|
||||
}
|
||||
|
||||
func nodeFromConfigNode(
|
||||
n config.Node) (*Node, error) {
|
||||
decodedSigningKey, err := keys.DecodeKeyFromString(
|
||||
|
|
|
@ -63,7 +63,7 @@ func New(loadFunc LoadFunc, opts ...Option) OCache {
|
|||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
if c.ttl != 0 {
|
||||
if c.ttl != 0 && c.gc != 0 {
|
||||
go c.ticker()
|
||||
}
|
||||
return c
|
||||
|
|
|
@ -75,7 +75,7 @@ func (s *service) Run(_ context.Context) error {
|
|||
}
|
||||
|
||||
func (s *service) getClient(ctx context.Context) (consensusproto.DRPCConsensusClient, error) {
|
||||
peer, err := s.pool.GetOneOf(ctx, s.nodeconf.ConsensusPeers())
|
||||
peer, err := s.pool.GetOneOf(ctx, s.nodeconf.GetLast().ConsensusPeers())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func (s *service) getClient(ctx context.Context) (consensusproto.DRPCConsensusCl
|
|||
}
|
||||
|
||||
func (s *service) dialClient(ctx context.Context) (consensusproto.DRPCConsensusClient, error) {
|
||||
peer, err := s.pool.DialOneOf(ctx, s.nodeconf.ConsensusPeers())
|
||||
peer, err := s.pool.DialOneOf(ctx, s.nodeconf.GetLast().ConsensusPeers())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/rpctest"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf/mock_nodeconf"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto/consensuserr"
|
||||
"github.com/golang/mock/gomock"
|
||||
|
@ -131,22 +131,34 @@ func newFixture(t *testing.T) *fixture {
|
|||
stream: make(chan consensusproto.DRPCConsensus_WatchLogStream),
|
||||
releaseStream: make(chan error),
|
||||
},
|
||||
nodeconf: nodeconf.New(),
|
||||
}
|
||||
fx.nodeconf = mock_nodeconf.NewMockService(fx.ctrl)
|
||||
fx.nodeconf.EXPECT().Init(gomock.Any())
|
||||
fx.nodeconf.EXPECT().Name().Return(nodeconf.CName).AnyTimes()
|
||||
fx.nodeconf.EXPECT().ConsensusPeers().Return([]string{"c1", "c2"}).AnyTimes()
|
||||
|
||||
fx.drpcTS = rpctest.NewTestServer()
|
||||
require.NoError(t, consensusproto.DRPCRegisterConsensus(fx.drpcTS.Mux, fx.testServer))
|
||||
fx.a.Register(fx.Service).
|
||||
Register(fx.nodeconf).
|
||||
Register(rpctest.NewTestPool().WithServer(fx.drpcTS))
|
||||
Register(rpctest.NewTestPool().WithServer(fx.drpcTS)).
|
||||
Register(&config.Config{Nodes: []config.Node{
|
||||
{
|
||||
PeerId: "c1",
|
||||
Types: []config.NodeType{config.NodeTypeConsensus},
|
||||
},
|
||||
{
|
||||
PeerId: "c2",
|
||||
Types: []config.NodeType{config.NodeTypeConsensus},
|
||||
},
|
||||
{
|
||||
PeerId: "c3",
|
||||
Types: []config.NodeType{config.NodeTypeConsensus},
|
||||
},
|
||||
}})
|
||||
return fx
|
||||
}
|
||||
|
||||
type fixture struct {
|
||||
Service
|
||||
nodeconf *mock_nodeconf.MockService
|
||||
nodeconf nodeconf.Service
|
||||
a *app.App
|
||||
ctrl *gomock.Controller
|
||||
testServer *testServer
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package consensusclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
|
||||
"github.com/cheggaaa/mb/v2"
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
|
||||
st := &stream{
|
||||
rpcStream: rpcStream,
|
||||
mb: mb.New((*consensusproto.WatchLogEvent)(nil), 100),
|
||||
mb: mb.New[*consensusproto.WatchLogEvent](100),
|
||||
}
|
||||
go st.readStream()
|
||||
return st
|
||||
|
@ -35,7 +36,8 @@ func (s *stream) UnwatchIds(logIds [][]byte) (err error) {
|
|||
}
|
||||
|
||||
func (s *stream) WaitLogs() []*consensusproto.WatchLogEvent {
|
||||
return s.mb.Wait()
|
||||
events, _ := s.mb.Wait(context.TODO())
|
||||
return events
|
||||
}
|
||||
|
||||
func (s *stream) Err() error {
|
||||
|
@ -54,7 +56,7 @@ func (s *stream) readStream() {
|
|||
s.mu.Unlock()
|
||||
return
|
||||
}
|
||||
if err = s.mb.Add(event); err != nil {
|
||||
if err = s.mb.Add(s.rpcStream.Context(), event); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/db"
|
||||
"github.com/cheggaaa/mb/v2"
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"github.com/mr-tron/base58"
|
||||
"go.uber.org/zap"
|
||||
"sync/atomic"
|
||||
|
@ -74,7 +74,7 @@ func (s *service) NewStream() *Stream {
|
|||
return &Stream{
|
||||
id: atomic.AddUint64(&s.lastStreamId, 1),
|
||||
logIds: make(map[string]struct{}),
|
||||
mb: mb.New(consensus.Log{}, 100),
|
||||
mb: mb.New[consensus.Log](100),
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package stream
|
|||
import (
|
||||
"context"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus"
|
||||
"github.com/cheggaaa/mb/v2"
|
||||
"github.com/cheggaaa/mb/v3"
|
||||
"go.uber.org/zap"
|
||||
"sync"
|
||||
)
|
||||
|
@ -30,13 +30,14 @@ func (s *Stream) LogIds() [][]byte {
|
|||
|
||||
// AddRecords adds new records to stream, called by objects
|
||||
func (s *Stream) AddRecords(logId []byte, records []consensus.Record) (err error) {
|
||||
return s.mb.Add(consensus.Log{Id: logId, Records: records})
|
||||
return s.mb.Add(context.TODO(), consensus.Log{Id: logId, Records: records})
|
||||
}
|
||||
|
||||
// WaitLogs wait for new log records
|
||||
// empty returned slice means that stream is closed
|
||||
func (s *Stream) WaitLogs() []consensus.Log {
|
||||
return s.mb.Wait()
|
||||
logs, _ := s.mb.Wait(context.TODO())
|
||||
return logs
|
||||
}
|
||||
|
||||
// WatchIds adds given ids to subscription
|
||||
|
@ -49,7 +50,7 @@ func (s *Stream) WatchIds(ctx context.Context, logIds [][]byte) {
|
|||
s.logIds[logIdKey] = struct{}{}
|
||||
if addErr := s.s.AddStream(ctx, logId, s); addErr != nil {
|
||||
log.Info("can't add stream for log", zap.Binary("logId", logId), zap.Error(addErr))
|
||||
_ = s.mb.Add(consensus.Log{
|
||||
_ = s.mb.Add(ctx, consensus.Log{
|
||||
Id: logId,
|
||||
Err: addErr,
|
||||
})
|
||||
|
|
|
@ -16,14 +16,17 @@ nodes:
|
|||
address: 127.0.0.1:4430
|
||||
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
|
||||
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
|
||||
address: 127.0.0.1:4431
|
||||
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
|
||||
address: 127.0.0.1:4432
|
||||
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
|
||||
types : ["tree", "file"]
|
||||
space:
|
||||
gcTTL: 60
|
||||
syncPeriod: 10
|
||||
|
|
|
@ -16,14 +16,17 @@ nodes:
|
|||
address: 127.0.0.1:4430
|
||||
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
|
||||
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
|
||||
address: 127.0.0.1:4431
|
||||
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
|
||||
address: 127.0.0.1:4432
|
||||
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
|
||||
types : ["tree", "file"]
|
||||
space:
|
||||
gcTTL: 60
|
||||
syncPeriod: 10
|
||||
|
|
|
@ -16,14 +16,17 @@ nodes:
|
|||
address: 127.0.0.1:4430
|
||||
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
|
||||
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
|
||||
address: 127.0.0.1:4431
|
||||
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
|
||||
address: 127.0.0.1:4432
|
||||
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
|
||||
types : ["tree", "file"]
|
||||
space:
|
||||
gcTTL: 60
|
||||
syncPeriod: 10
|
||||
|
|
|
@ -16,14 +16,17 @@ nodes:
|
|||
address: 127.0.0.1:4430
|
||||
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
|
||||
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
|
||||
address: 127.0.0.1:4431
|
||||
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
|
||||
address: 127.0.0.1:4432
|
||||
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
|
||||
types : ["tree", "file"]
|
||||
space:
|
||||
gcTTL: 60
|
||||
syncPeriod: 10
|
||||
|
|
|
@ -16,14 +16,17 @@ nodes:
|
|||
address: 127.0.0.1:4430
|
||||
signingKey: 3mzfKBWtn7mitFEgq8u4eysWOJ6ySbUs49irfHwcuOmi1YMpobz9anoqd4yaT1owZiRPYXqx5k2Z4sNVRE3kXA==
|
||||
encryptionKey: MIIEpQIBAAKCAQEA3U7b4w9JTKE3TLM1WQ5iqdLbvUuozMp/hDEg7S15Gr6wrtLomMSBkfmVQ3Cu+CHdxAFqUFClItYlSFgtZWIFiSiQxCeaN2dmgczd9T4TlRAw6y6uJXtT9r7FIgizPP4B0/tnzPI6yYgpdwzCV2nRSjw3mMr5Nav3QYs18kYrJ1/Np2Wob5HOoRTUD++pPrToevTb7GNL/irrC8wXSE7oU6S7ix6Nh9vzEHg/V5FONBF/wWD/ri7Gy0j0qgUQ+gjxLWKr8xPDnRAve13zzo+54lGCyVvlm/rwCY9Jx378V1IuRx+S8F/GFuVozHD4XVaoSTtpCWPBQNSKDXgaIIKDowIDAQABAoIBACpMXj6ht1LMJXOldPbWhwkKYjFl+pdZxNGRSkfKvzDbbY2chhRcyp8J4vuG2ApY/rftxVIgd8+Wun1/TP3ppEE43aKAJzubqb35WBr9iGSfOZpZy7MiRUQN5kPBAfEQY20OyiIj0hSez74PVD283eGgbMfpU4Rsn8+JOgBaZPkbPViJLJY8PyHU6vwWw60dye1iJTz9yuBtoEqY0XKxnLaVXTQaWx0Te+VYU8twxDgXFWRaXtHuk7xnxOkCZDLrzIvuOYa5lsLoT8K62LDeXbyHBPhbdW0j4ZYzAOTsaUWpjuJzef9aj3JJdfyADiqb5iu6HHksvKzkZEau34zjilECgYEA/c8ZJm62uJMHNssTJYiLRw89l5hYwIZ/1TXdFRF8+xrTin5opYjpscSTO5bY2IYqLx2xuPiJCY1eGGB9L/RtkaVh51ySzq0d+4zpPIRKFcOOgdxHwlgoCgIhQECyfJZNMFGBUIlPXZ/phvXOXRvWFzDPhqThenVG2QzF+wLP0AUCgYEA3zfviQFJ1FOKJMozYO3tUZFmsIrAcO9hfuE7uuWz0Fw2m1XiwxjuOr1RbsSsh/lKke2h4tiGrlfiFhwCpIp91NkVTFrtFOQxbDxkYLkFiWkZDkOaK9YhKMa2cgEm3p+RGawokjbm51LKf+cbYN9xGaAe3y2WzIE4kNpfWE4SXYcCgYEAoagcrrvpqZoMCDxED63ud+4fHsUsEkQYe6Z5EAg5gH5PqnBlGrofjthTpqqnpxGdILFbFyNFtU3TVtduJPMcLp4Vw5TU9MqSxDu1+pOP1FjgFZpGImSf6+/7Wb9bb7sToujm4nLymAFYblt1exxVuiOeqnWuH58+5tQZ7YyW7DkCgYEAl7WuqZEkmpiEpWh/7vsGdo+6GXbUQG2R9+gg7m+7/HsP6hc/XZYOJAIT3JLzKB84nWHCyyiasNeuI5S5/xbZWtaH8TNDOxW0uXl6R3q41qGFk/pCSFTqiIo16dn6jwgoWCh4EpgZ61KLqs5p/zcd6Wq4ULrtaOTSizC/6IZ3WPUCgYEA6xCJy3+ICCgr8/c7hfd2Ylb3aOsXIffdgALhXjDcrNUCqgB4R+S3WReAwrABemQGl4tySQE/1f3Ru7SzMMciFogGyJ/YSXqSi6Y8oDD7MqlKPiWlN6WY1nSRMlLbkUOqpA5JaDM0kcmXjZpBBQr277GOnh9uKN8zUy5xoptctxI=
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWLtuKtCPBYrFJV1NdejiCr2s614ppe9rmUXnkTHtAUD5U
|
||||
address: 127.0.0.1:4431
|
||||
signingKey: 07JMoW5cQUtGO9nNIGQo9e99b7Wf/4YvTtNEA0lt4gCkmhwB1EB9ay+kitxVJJgmdyGLxbUUlGqwXsAj0zlHWw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA7cA6J/icl8wseeXkt8oJr5AeYadUAG5EdCOdHj4S/Z7ivff4MOIKAeQITpq+rqhmXxOePYXSpQXE20Y9PW9tuw4gzOuq1ylSG/MWMcLDH1eIxg66rnmUqUbdiW4GGJjVjc9jvN0Up+MfSrUF6fM0jWTFoXVJQIeQQGERCIYjFzjfBl1xYvPghdxNgei/K5ZGYRggT28143XdIH4KTXGtp51hAKoyY9eCqYMtm9wvjxazhPVxO2CsYaqMxBLshY3jfHNqJnx8u6+h4Bl4uUcdbLNUgMcEgk7ehbQp2K0CqNoKXxbCTI6V57UVcJHDIaO5B6FyR6BguzHHNPJ4yd3q9wIDAQABAoIBAQCm2Mf3VRlPzhFIWnVwJXE2q8Umcu8Yfkm712Jj3twk8GPfPS4H4Bl1yjmqMB6xI6zz/CiItGlnNe04lMpVWuV+6CNMq/ZwmKbuxmFE+pFEZYGuvJd16gzR3tGJqJTOnjMAGhK8b8oXJ+TF4NQNooe20ol/DXgiuQAargPuH3RwzjYmF3N8VI4KUc3LaG4TwVXn4LwPOxrQSnfwJlZwLml1HAKOV0qcG0mXX6ZXOpoVhEoRPdQyUHc8ZW+53Agbtind7bYh5TsMVDFUrcgNwnwTOsWjil049la1IJO2uMRluacKlrtyzEp6zqrW8ZJO7mYAO69x4WyGqf2ZgIdA6djBAoGBAPqRHWAIgPa80eXbwCYkRtUG/ONBsQGi7+wm6nyhkXvNXJeokgH2DCgLH2+fW2scfOJuZc9r5WftEjOBvNfr2LDcwdyTSTh21WYcPSZx9HDf2d5/SWTcjNcyU0b5qfWIUKi/Zm9UY7r3X7yMA5dUD/cvu1PBJ5NWFrK1Gm2ph44dAoGBAPLn+LkHweU0fbxQq/76T5yVVpMKUaE9xwrJlUxEDPAQGnLPbFg4JeUt/YPhsOV85W4c4oQE+uFZrF0uf+1fEnS6MOJ+sq668upzC2hBp1B5138wM7615v1rvXVVH6qXfFop67FdBzPHt1NAN43mEIBZHTQ5hSVXFlYSZp9mxuEjAoGBAKCzUVO2IIAeub/iIGpV+dfGk4ptJ0kVZyreCqXEObpdC3V496uqUkGcYJ0GZ2ta6f2PMFzHpmnw8it2mdchu+gyrWL6U4uTK2pB0jZF/7Ak4WaB3GCD0xBxhleO6CJBOvn/R4M/bHcNEKmsYuE7WMIAKvScfPVR0VzsKfcLM5VBAoGAVvWg32zdh1bBZLdku8WU1rPH6KAbFSRuq3f7UPBTyWWaclu7p+GB/4f1aE9V6vJJmKASn7zArAhUYo+REMOmcc9uTMea5F7dM/23qb1HTtIvycLR44ZviW4Wx3iP+5x70jOLw1VQjMME6HLm8I/afHhqshWdiv6ganPv9UTwEg0CgYBSDi2dqg8F7ij5CN+LMDLSn3b8GCw+7efGIt7imm/O2V/FlHD40IA6qGg6DXNQrnoZQt94nMb1cZEvm1dxi6rmQNrhCyoMogAaPqgFhZGq1OjmhVZiXFUWy4WAcjdzFc9wZd3/XtaofRKHLK+ngTFhhVApKypLk3Rg9bCAAjzyVg==
|
||||
types : ["tree", "file"]
|
||||
- peerId: 12D3KooWDCypXSyN6ppuMZGxVnBd1ZQCMV4y7Bn187S4duYmf8rA
|
||||
address: 127.0.0.1:4432
|
||||
signingKey: SGyNE0dFaQgtgNuzdcO7LB+TEz9VHAOtlQLk6WWkrkQyXiZV3casg8Q2/4PO1Oylc8Fu72RU001Hclj5JCbiLw==
|
||||
encryptionKey: MIIEpAIBAAKCAQEA0k3mw4FyexRkLgLjHzYs4Ppeyv6r9ZrP00imNf15JTuM8ajMx5oJX7JQTm8KOLRJjUdZZAd5Gtp0ezfYAQK1ZjEWwCmfp8j8FBgJIDSLpjxl88SXMLgATXYfhklnQvKlQjs/X3Ka4zdTrav2tMH9IAo6TSNZhlPQNsUory1SGHs+KqHv4p0sG8oWuKYhfBj8rWHQdUVptkIBKgojFDeJJD04Tbf9kUakbK/8KuXB6zF5H4WN3p4rMMwkClyTGeYO4LDg5TzVn8NnUi3/b/vO/3us1G/TMoRe/6umUfpQxrwo+7S2T6A4YwetWRp6xALLhp+HfAWnn0lA/D8/w1WpKwIDAQABAoIBAQC5cdQxRa5rddm48PbSCPWeFWkNW3DLDI6CYyedqDvxZwer+QtKXzww1I4X+7ZptiC9odLjb+uMkGHyXZXtnjPTPyounQWZ8JLILUGu0mbqWYwVXp9raHVr2OOHiKaz1D+BnbkOM4L9JUZ2eJL9ZaoNXLd4WdmRp8qM4WI0xqQDzOANx2HhyL/+dJmQeIUND+pdeH+Z+fYowU3ho32txNvBnMXQhF1T5K9i1VO5W49RAjIRbENsT+paPGKbNubDHRt1j36ktK4eC4HSdgv8tccdsGyrEiIbAt1XsTZfM8ie4D3A8RhSxiTC6Fkgv6vIm+iFTLzBFZKesOBcd8sfKeyBAoGBAOts5PQQJhldPDzlbnqzxMOR98WHbkVZjCqWSkNA34vqyFuPcRuX0rHK/qpg23ilbUP0fGMDTGgFzTt51FZLL16SXyRfjNhzjdmryryeddQwbp92ta2GEgnU6t1FyCuSCtcLDKJd/D9A9dC5UI6z+ES4TOnbR3nakXK9t4cUOFthAoGBAOSu+wL+SEA5erR+m3LpOsELK68CCJQPxn3VpoVfJZawgF+fEoXVMLTERxJput1+ADomIEdNc9ex86TjKx9gJ4piNHscRPFeT/AgESOIGHLOc1gk2DPqNj6wBIarUJQ9t4KcHScboh1dTPJeqqv2NSwIiLQoqFUIhfKZLnrW3zwLAoGBAJh0hC+o5YM3ZXLqAIllMN6VACbidP5j5ukNOjojIKCzAdyJH24G+2I3WoNrBbUzK3b+NC7KTAhw+V6ynlbjiWFs2D/twH/LFOkI3tkWpKcsVfbeIPimAbhsMUvpjJ7qjCqF9UCQLHGp14W6+/ftg7C8yNIINlkquVXclaTb60MBAoGAPqmL8ogG+EJH00mWAujRxq/u6meePiQMedKfbJBj1mTK6GjIRI/kZsQZzXvXTnYGTejAk4kvov0KDDaLTG+mpg6+3rUiVxlGwj+nMptKR7s2dAK0k5UsBAVrWBN9YwF+VXW9r0etJmq4ePljvvcaHtS/0M4LQjGxsoYy7EoQpX0CgYAhnf0McB7F1MxSjB0soMNv/v5utVzVihS3re2yKNdkI/YUEMB+yU3Q4gh+OljjBM6Y5To3BsQBAx4l2CysMKFHjIE/5AtdbvIS+chZZqB3vcZXSayvX8P1Z1uFdw/saiO2cRDJmR+TxaOPa2C9SzDoNTACthwLErHfzvEvVroKmw==
|
||||
types : ["tree", "file"]
|
||||
space:
|
||||
gcTTL: 60
|
||||
syncPeriod: 10
|
||||
|
|
46
filenode/fileservice/blockservice.go
Normal file
46
filenode/fileservice/blockservice.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package fileservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonfile/ipfsstore"
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
exchange "github.com/ipfs/go-ipfs-exchange-interface"
|
||||
)
|
||||
|
||||
type blockService struct {
|
||||
store ipfsstore.IPFSStore
|
||||
}
|
||||
|
||||
func (bs *blockService) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
|
||||
return bs.store.Get(ctx, c)
|
||||
}
|
||||
|
||||
func (bs *blockService) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
|
||||
return bs.store.GetMany(ctx, ks)
|
||||
}
|
||||
|
||||
func (bs *blockService) Blockstore() blockstore.Blockstore {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *blockService) Exchange() exchange.Interface {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *blockService) AddBlock(ctx context.Context, b blocks.Block) error {
|
||||
return bs.store.Add(ctx, []blocks.Block{b})
|
||||
}
|
||||
|
||||
func (bs *blockService) AddBlocks(ctx context.Context, b []blocks.Block) error {
|
||||
return bs.store.Add(ctx, b)
|
||||
}
|
||||
|
||||
func (bs *blockService) DeleteBlock(ctx context.Context, c cid.Cid) error {
|
||||
return bs.store.Delete(ctx, c)
|
||||
}
|
||||
|
||||
func (bs *blockService) Close() error {
|
||||
return bs.store.Close()
|
||||
}
|
36
filenode/fileservice/fileservice.go
Normal file
36
filenode/fileservice/fileservice.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package fileservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
"github.com/ipfs/go-merkledag"
|
||||
)
|
||||
|
||||
const CName = "filenode.fileservice"
|
||||
|
||||
type FileService interface {
|
||||
app.ComponentRunnable
|
||||
}
|
||||
|
||||
type fileService struct {
|
||||
blockService *blockService
|
||||
dagService ipld.DAGService
|
||||
}
|
||||
|
||||
func (fs *fileService) Init(a *app.App) (err error) {
|
||||
fs.dagService = merkledag.NewDAGService(fs.blockService)
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *fileService) Name() string {
|
||||
return CName
|
||||
}
|
||||
|
||||
func (fs *fileService) Run(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *fileService) Close(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
54
filenode/go.mod
Normal file
54
filenode/go.mod
Normal file
|
@ -0,0 +1,54 @@
|
|||
module github.com/anytypeio/go-anytype-infrastructure-experiments/filenode
|
||||
|
||||
go 1.19
|
||||
|
||||
replace github.com/anytypeio/go-anytype-infrastructure-experiments/common => ../common
|
||||
|
||||
require github.com/anytypeio/go-anytype-infrastructure-experiments/common v0.0.0-00010101000000-000000000000
|
||||
|
||||
require (
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/uuid v1.2.0 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/ipfs/bbloom v0.0.4 // indirect
|
||||
github.com/ipfs/go-block-format v0.0.3 // indirect
|
||||
github.com/ipfs/go-blockservice v0.3.0 // indirect
|
||||
github.com/ipfs/go-cid v0.3.2 // indirect
|
||||
github.com/ipfs/go-datastore v0.5.0 // indirect
|
||||
github.com/ipfs/go-ipfs-blockstore v1.2.0 // indirect
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
|
||||
github.com/ipfs/go-ipfs-exchange-interface v0.1.0 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
|
||||
github.com/ipfs/go-ipld-cbor v0.0.5 // indirect
|
||||
github.com/ipfs/go-ipld-format v0.4.0 // indirect
|
||||
github.com/ipfs/go-ipld-legacy v0.1.0 // indirect
|
||||
github.com/ipfs/go-log v1.0.5 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/ipfs/go-merkledag v0.8.0 // indirect
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
|
||||
github.com/ipfs/go-verifcid v0.0.1 // indirect
|
||||
github.com/ipld/go-codec-dagpb v1.3.1 // indirect
|
||||
github.com/ipld/go-ipld-prime v0.16.0 // indirect
|
||||
github.com/jbenet/goprocess v0.1.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.1.1 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.1 // indirect
|
||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.23.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
1115
filenode/go.sum
Normal file
1115
filenode/go.sum
Normal file
File diff suppressed because it is too large
Load diff
3
go.work
3
go.work
|
@ -1,9 +1,10 @@
|
|||
go 1.19
|
||||
|
||||
use (
|
||||
./client
|
||||
./common
|
||||
./consensus
|
||||
./filenode
|
||||
./node
|
||||
./client
|
||||
./util
|
||||
)
|
||||
|
|
|
@ -7,8 +7,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUu
|
|||
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
|
||||
github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
|
||||
github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=
|
||||
|
@ -49,19 +47,19 @@ github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQy
|
|||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 h1:Ak8CrdlwwXwAZxzS66vgPt4U8yUZX7JwLvVR58FN5jM=
|
||||
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
|
||||
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
|
||||
github.com/ipfs/go-ds-badger v0.3.0 h1:xREL3V0EH9S219kFFueOYJJTcjgNSZ2HY1iSvN7U1Ro=
|
||||
github.com/ipfs/go-ds-leveldb v0.5.0 h1:s++MEBbD3ZKc9/8/njrn4flZLnCuY9I79v94gBUNumo=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
|
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
|
|
@ -10,16 +10,6 @@ message BlockSync {
|
|||
|
||||
message Msg {
|
||||
|
||||
}
|
||||
|
||||
service Space {
|
||||
rpc Diff(Msg) returns (Msg);
|
||||
|
||||
// subscription service:
|
||||
// service.Broadcast(ss)
|
||||
rpc ObjectSyncStream(stream Msg) returns (stream Msg);
|
||||
|
||||
|
||||
}
|
||||
|
||||
service File {
|
||||
|
@ -27,12 +17,3 @@ service File {
|
|||
rpc PushCID(Msg) returns (Msg);
|
||||
}
|
||||
|
||||
service StrongLog { // ACL Log
|
||||
rpc PushACL(Msg) returns (Msg);
|
||||
rpc StartTransaction();
|
||||
}
|
||||
|
||||
service Replication {
|
||||
//
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue