Files
go-cart-actor/rpc-pool.go
matst80 65a969443a stuff
2024-11-08 21:58:28 +01:00

131 lines
2.5 KiB
Go

package main
import (
"encoding/binary"
"net"
)
const (
RemoteGetState = uint16(0x01)
RemoteHandleMessage = uint16(0x02)
)
type RemoteGrainPool struct {
Hosts []string
grains map[CartId]RemoteGrain
}
func (id CartId) String() string {
return string(id[:])
}
func ToCartId(id string) CartId {
var result [16]byte
copy(result[:], []byte(id))
return result
}
type RemoteGrain struct {
client net.Conn
Id CartId
Address string
}
func NewRemoteGrain(id CartId, address string) *RemoteGrain {
return &RemoteGrain{
Id: id,
Address: address,
}
}
func (g *RemoteGrain) Connect() error {
if g.client == nil {
client, err := net.Dial("tcp", g.Address)
if err != nil {
return err
}
g.client = client
}
return nil
}
type Packet struct {
Version uint16
MessageType uint16
Id CartId
DataLength uint16
}
func (g *RemoteGrain) SendPacket(messageType uint16, data []byte) error {
binary.Write(g.client, binary.LittleEndian, Packet{
Version: 2,
MessageType: messageType,
Id: g.Id,
DataLength: uint16(len(data)),
})
return binary.Write(g.client, binary.LittleEndian, data)
}
func (g *RemoteGrain) HandleMessage(message *Message, isReplay bool) ([]byte, error) {
data, err := GetData(message.Write)
if err != nil {
return nil, err
}
err = g.SendPacket(RemoteHandleMessage, data)
result := make([]byte, 65535)
g.client.Read(result)
return result, err
}
func (g *RemoteGrain) GetId() CartId {
return g.Id
}
func (g *RemoteGrain) GetCurrentState() (Grain, error) {
var reply CartGrain
err := g.SendPacket(RemoteGetState, nil)
if err != nil {
return nil, err
}
return &reply, err
}
func NewRemoteGrainPool(addr ...string) *RemoteGrainPool {
return &RemoteGrainPool{
Hosts: addr,
grains: make(map[CartId]RemoteGrain),
}
}
func (p *RemoteGrainPool) findRemoteGrain(id CartId) *RemoteGrain {
grain, ok := p.grains[id]
if !ok {
return nil
}
return &grain
}
func (p *RemoteGrainPool) Process(id CartId, messages ...Message) (interface{}, error) {
var result interface{}
var err error
grain := p.findRemoteGrain(id)
if grain == nil {
grain = NewRemoteGrain(id, p.Hosts[0])
grain.Connect()
p.grains[id] = *grain
}
for _, message := range messages {
result, err = grain.HandleMessage(&message, false)
}
return result, err
}
func (p *RemoteGrainPool) Get(id CartId) (Grain, error) {
grain := p.findRemoteGrain(id)
if grain == nil {
return nil, nil
}
return grain.GetCurrentState()
}