115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package consensusrpc
|
|
|
|
import (
|
|
"context"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/db"
|
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/stream"
|
|
"time"
|
|
)
|
|
|
|
const CName = "consensus.consensusrpc"
|
|
|
|
func New() app.Component {
|
|
return &consensusRpc{}
|
|
}
|
|
|
|
type consensusRpc struct {
|
|
db db.Service
|
|
stream stream.Service
|
|
}
|
|
|
|
func (c *consensusRpc) Init(a *app.App) (err error) {
|
|
c.db = a.MustComponent(db.CName).(db.Service)
|
|
c.stream = a.MustComponent(stream.CName).(stream.Service)
|
|
return consensusproto.DRPCRegisterConsensus(a.MustComponent(server.CName).(server.DRPCServer), c)
|
|
}
|
|
|
|
func (c *consensusRpc) Name() (name string) {
|
|
return CName
|
|
}
|
|
|
|
func (c *consensusRpc) AddLog(ctx context.Context, req *consensusproto.AddLogRequest) (*consensusproto.Ok, error) {
|
|
if err := c.db.AddLog(ctx, logFromProto(req.Log)); err != nil {
|
|
return nil, err
|
|
}
|
|
return &consensusproto.Ok{}, nil
|
|
}
|
|
|
|
func (c *consensusRpc) AddRecord(ctx context.Context, req *consensusproto.AddRecordRequest) (*consensusproto.Ok, error) {
|
|
if err := c.db.AddRecord(ctx, req.LogId, recordFromProto(req.Record)); err != nil {
|
|
return nil, err
|
|
}
|
|
return &consensusproto.Ok{}, nil
|
|
}
|
|
|
|
func (c *consensusRpc) WatchLog(req *consensusproto.WatchLogRequest, rpcStream consensusproto.DRPCConsensus_WatchLogStream) error {
|
|
stream, err := c.stream.Subscribe(rpcStream.Context(), req.LogId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer stream.Close()
|
|
var logSent bool
|
|
for {
|
|
if !logSent {
|
|
if err = rpcStream.Send(&consensusproto.WatchLogEvent{
|
|
LogId: req.LogId,
|
|
Records: recordsToProto(stream.Records()),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
recs := stream.WaitRecords()
|
|
if len(recs) == 0 {
|
|
return rpcStream.Close()
|
|
}
|
|
if err = rpcStream.Send(&consensusproto.WatchLogEvent{
|
|
LogId: req.LogId,
|
|
Records: recordsToProto(recs),
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func logFromProto(log *consensusproto.Log) consensus.Log {
|
|
return consensus.Log{
|
|
Id: log.Id,
|
|
Records: recordsFromProto(log.Records),
|
|
}
|
|
}
|
|
|
|
func recordsFromProto(recs []*consensusproto.Record) []consensus.Record {
|
|
res := make([]consensus.Record, len(recs))
|
|
for i, rec := range recs {
|
|
res[i] = recordFromProto(rec)
|
|
}
|
|
return res
|
|
}
|
|
|
|
func recordFromProto(rec *consensusproto.Record) consensus.Record {
|
|
return consensus.Record{
|
|
Id: rec.Id,
|
|
PrevId: rec.PrevId,
|
|
Payload: rec.Payload,
|
|
Created: time.Unix(int64(rec.CreatedUnix), 0),
|
|
}
|
|
}
|
|
|
|
func recordsToProto(recs []consensus.Record) []*consensusproto.Record {
|
|
res := make([]*consensusproto.Record, len(recs))
|
|
for i, rec := range recs {
|
|
res[i] = &consensusproto.Record{
|
|
Id: rec.Id,
|
|
PrevId: rec.PrevId,
|
|
Payload: rec.Payload,
|
|
CreatedUnix: uint64(rec.Created.Unix()),
|
|
}
|
|
}
|
|
return res
|
|
}
|