stuffs
This commit is contained in:
190
main.go
190
main.go
@@ -1,143 +1,111 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/rpc"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GrainServer struct {
|
||||
Host string
|
||||
}
|
||||
func spawn(id string) Grain {
|
||||
|
||||
type Grain interface {
|
||||
HandleMessage(message *Message, reply *CartGrain) error
|
||||
}
|
||||
|
||||
func NewServer(hostname string) *GrainServer {
|
||||
return &GrainServer{
|
||||
Host: hostname,
|
||||
ret := &CartGrain{
|
||||
Id: id,
|
||||
Items: []CartItem{},
|
||||
storageMessages: []Message{},
|
||||
TotalPrice: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
err := loadMessages(ret, id)
|
||||
if err != nil {
|
||||
log.Printf("Error loading messages for grain %s: %v\n", id, err)
|
||||
}
|
||||
return &addr, nil
|
||||
return ret
|
||||
}
|
||||
|
||||
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
|
||||
func init() {
|
||||
os.Mkdir("data", 0755)
|
||||
gob.Register(CartItem{})
|
||||
gob.Register(Message{})
|
||||
}
|
||||
|
||||
type ServerPool interface {
|
||||
GetOrSpawn(id string, ttl time.Time) (*string, error)
|
||||
type App struct {
|
||||
pool *GrainLocalPool
|
||||
storage *DiskStorage
|
||||
}
|
||||
|
||||
type WebServer struct {
|
||||
ServerPool ServerPool
|
||||
func (a *App) HandleGet(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
grain, err := a.pool.GetOrSpawn(id, spawn)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(grain)
|
||||
}
|
||||
|
||||
type MemoryServerPool struct {
|
||||
port int
|
||||
local *GrainServer
|
||||
pool map[string]*string
|
||||
func (a *App) HandleAddSku(w http.ResponseWriter, r *http.Request) {
|
||||
id := r.PathValue("id")
|
||||
sku := r.PathValue("sku")
|
||||
grain, err := a.pool.GetOrSpawn(id, spawn)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
message := &Message{
|
||||
Type: "add",
|
||||
Content: sku,
|
||||
}
|
||||
var reply CartGrain
|
||||
err = grain.HandleMessage(message, false, &reply)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(reply)
|
||||
}
|
||||
|
||||
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
|
||||
func (a *App) Save() error {
|
||||
for id, grain := range a.pool.GetGrains() {
|
||||
err := a.storage.Store(id, grain)
|
||||
if err != nil {
|
||||
log.Printf("Error saving grain %s: %v\n", id, err)
|
||||
}
|
||||
//go http.Serve(l, nil)
|
||||
a := fmt.Sprintf("localhost:%d", prt)
|
||||
p.pool[id] = &a
|
||||
addr = &a
|
||||
}
|
||||
return addr, nil
|
||||
return a.storage.saveState()
|
||||
}
|
||||
|
||||
func (a *App) HandleSave(w http.ResponseWriter, r *http.Request) {
|
||||
err := a.Save()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
} else {
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Create a new instance of the server
|
||||
pool := &MemoryServerPool{
|
||||
port: 1337,
|
||||
pool: make(map[string]*string),
|
||||
local: NewServer("localhost"),
|
||||
storage, err := NewDiskStorage("data/state.json")
|
||||
if err != nil {
|
||||
log.Printf("Error loading state: %v\n", err)
|
||||
}
|
||||
app := &App{
|
||||
pool: NewGrainLocalPool(1000, 5*time.Minute),
|
||||
storage: storage,
|
||||
}
|
||||
|
||||
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)))
|
||||
})
|
||||
mux.HandleFunc("GET /{id}", app.HandleGet)
|
||||
mux.HandleFunc("GET /{id}/add/{sku}", app.HandleAddSku)
|
||||
mux.HandleFunc("GET /save", app.HandleSave)
|
||||
http.ListenAndServe(":8080", mux)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user