Files
go-cart-actor/main.go
matst80 0f23ae0e9a first
2024-11-06 12:54:46 +01:00

144 lines
2.9 KiB
Go

package main
import (
"fmt"
"net"
"net/http"
"net/rpc"
"time"
)
type GrainServer struct {
Host string
}
type Grain interface {
HandleMessage(message *Message, reply *CartGrain) error
}
func NewServer(hostname string) *GrainServer {
return &GrainServer{
Host: hostname,
}
}
func (s *GrainServer) Start(port int, instance Grain) (net.Listener, error) {
rpc.Register(instance)
rpc.HandleHTTP()
return net.Listen("tcp", fmt.Sprintf(":%d", port))
}
type CartGrain struct {
Skus []string
}
type Message struct {
Type string
Content string
}
type Registry interface {
Register(address string, id string) error
Get(id string) (*string, error)
}
type MemoryRegistry struct {
registry map[string]string
}
func (r *MemoryRegistry) Register(address string, id string) error {
r.registry[id] = address
return nil
}
func (r *MemoryRegistry) Get(id string) (*string, error) {
addr, ok := r.registry[id]
if !ok {
return nil, fmt.Errorf("id not found")
}
return &addr, nil
}
func (c *CartGrain) HandleMessage(message *Message, reply *CartGrain) error {
fmt.Println("CartGrain received message: ", message)
c.Skus = append(c.Skus, message.Content)
*reply = *c
return nil
}
type ServerPool interface {
GetOrSpawn(id string, ttl time.Time) (*string, error)
}
type WebServer struct {
ServerPool ServerPool
}
type MemoryServerPool struct {
port int
local *GrainServer
pool map[string]*string
}
func (p *MemoryServerPool) GetOrSpawn(id string, ttl time.Duration) (*string, error) {
addr, ok := p.pool[id]
if !ok {
prt := p.port
p.port++
s := NewServer("localhost")
_, e := s.Start(prt, &CartGrain{})
if e != nil {
return nil, e
}
//go http.Serve(l, nil)
a := fmt.Sprintf("localhost:%d", prt)
p.pool[id] = &a
addr = &a
}
return addr, nil
}
func main() {
// Create a new instance of the server
pool := &MemoryServerPool{
port: 1337,
pool: make(map[string]*string),
local: NewServer("localhost"),
}
mux := http.NewServeMux()
mux.HandleFunc("GET /{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
addr, err := pool.GetOrSpawn(id, time.Hour*1)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte(*addr))
})
mux.HandleFunc("GET /add/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
addr, err := pool.GetOrSpawn(id, time.Hour*1)
if err != nil {
w.WriteHeader(http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
var cart CartGrain
client, err := rpc.DialHTTP("tcp", *addr)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
err = client.Call("CartGrain.HandleMessage", &Message{Type: "add", Content: "123"}, &cart)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write([]byte(fmt.Sprintf("Cart: %v", cart.Skus)))
})
http.ListenAndServe(":8080", mux)
}