missing updates #5
@@ -113,7 +113,7 @@ metadata:
|
||||
arch: arm64
|
||||
name: cart-actor-arm64
|
||||
spec:
|
||||
replicas: 0
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cart-actor
|
||||
|
||||
102
frames.go
102
frames.go
@@ -1,102 +0,0 @@
|
||||
package main
|
||||
|
||||
// Minimal frame abstractions retained after removal of the legacy TCP/frame
|
||||
// networking layer. These types remain only to avoid a wide cascading refactor
|
||||
// across existing grain / pool logic that still constructs and passes
|
||||
// FrameWithPayload objects internally.
|
||||
//
|
||||
// The original responsibilities this replaces:
|
||||
// - Binary framing, checksums, network IO
|
||||
// - Distinction between request / reply frame types
|
||||
//
|
||||
// What remains:
|
||||
// - A light weight container (FrameWithPayload) used as an in‑process
|
||||
// envelope for status code + typed marker + payload bytes (JSON or proto).
|
||||
// - Message / status constants referenced in existing code paths.
|
||||
//
|
||||
// Recommended future cleanup (post‑migration):
|
||||
// - Remove FrameType entirely and replace with enumerated semantic results
|
||||
// or error values.
|
||||
// - Replace FrameWithPayload with a struct { Status int; Data []byte }.
|
||||
// - Remove remote_* reply type branching once all callers rely on gRPC
|
||||
// status + strongly typed responses.
|
||||
//
|
||||
// For now we keep this minimal surface to keep the gRPC migration focused.
|
||||
|
||||
type (
|
||||
// FrameType is a symbolic identifier carried through existing code paths.
|
||||
// No ordering or bit semantics are required anymore.
|
||||
FrameType uint32
|
||||
StatusCode uint32
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
Type FrameType
|
||||
StatusCode StatusCode
|
||||
Length uint32
|
||||
// Checksum retained for compatibility; no longer validated.
|
||||
Checksum uint32
|
||||
}
|
||||
|
||||
// FrameWithPayload wraps a Frame with an opaque payload.
|
||||
// Payload usually contains JSON encoded cart state or an error message.
|
||||
type FrameWithPayload struct {
|
||||
Frame
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Legacy Frame Type Constants (minimal subset still referenced)
|
||||
// -----------------------------------------------------------------------------
|
||||
const (
|
||||
RemoteGetState = FrameType(0x01)
|
||||
RemoteHandleMutation = FrameType(0x02)
|
||||
ResponseBody = FrameType(0x03) // (rarely used; kept for completeness)
|
||||
RemoteGetStateReply = FrameType(0x04)
|
||||
RemoteHandleMutationReply = FrameType(0x05)
|
||||
RemoteCreateOrderReply = FrameType(0x06)
|
||||
)
|
||||
|
||||
// MakeFrameWithPayload constructs an in‑process frame wrapper.
|
||||
// Length & Checksum are filled for backward compatibility (no validation logic
|
||||
// depends on the checksum anymore).
|
||||
func MakeFrameWithPayload(msg FrameType, statusCode StatusCode, payload []byte) FrameWithPayload {
|
||||
length := uint32(len(payload))
|
||||
return FrameWithPayload{
|
||||
Frame: Frame{
|
||||
Type: msg,
|
||||
StatusCode: statusCode,
|
||||
Length: length,
|
||||
Checksum: (uint32(msg) + uint32(statusCode) + length) / 8, // simple legacy formula
|
||||
},
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
// Clone creates a shallow copy of the frame, duplicating the payload slice.
|
||||
func (f *FrameWithPayload) Clone() *FrameWithPayload {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
cp := make([]byte, len(f.Payload))
|
||||
copy(cp, f.Payload)
|
||||
return &FrameWithPayload{
|
||||
Frame: f.Frame,
|
||||
Payload: cp,
|
||||
}
|
||||
}
|
||||
|
||||
// NewErrorFrame helper for creating an error frame with a textual payload.
|
||||
func NewErrorFrame(msg FrameType, code StatusCode, err error) FrameWithPayload {
|
||||
var b []byte
|
||||
if err != nil {
|
||||
b = []byte(err.Error())
|
||||
}
|
||||
return MakeFrameWithPayload(msg, code, b)
|
||||
}
|
||||
|
||||
// IsSuccess returns true if the status code indicates success in the
|
||||
// conventional HTTP style range (200–299). This mirrors previous usage patterns.
|
||||
func (f *FrameWithPayload) IsSuccess() bool {
|
||||
return f != nil && f.StatusCode >= 200 && f.StatusCode < 300
|
||||
}
|
||||
6
main.go
6
main.go
@@ -249,20 +249,20 @@ func main() {
|
||||
return
|
||||
}
|
||||
cartId := ToCartId(cookie.Value)
|
||||
_, err = syncedServer.pool.Apply(cartId, getCheckoutOrder(r.Host, cartId))
|
||||
order, err = syncedServer.CreateOrUpdateCheckout(r.Host, cartId)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
}
|
||||
// v2: Apply now returns *CartGrain; order creation handled inside grain (no payload to unmarshal)
|
||||
} else {
|
||||
prevOrder, err := KlarnaInstance.GetOrder(orderId)
|
||||
order, err = KlarnaInstance.GetOrder(orderId)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
order = prevOrder
|
||||
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.Header().Set("Permissions-Policy", "payment=(self \"https://js.stripe.com\" \"https://m.stripe.network\" \"https://js.playground.kustom.co\")")
|
||||
|
||||
@@ -216,48 +216,51 @@ func (s *PoolServer) HandleConfirmation(w http.ResponseWriter, r *http.Request,
|
||||
return json.NewEncoder(w).Encode(order)
|
||||
}
|
||||
|
||||
func (s *PoolServer) HandleCheckout(w http.ResponseWriter, r *http.Request, id CartId) error {
|
||||
// Build checkout meta (URLs derived from host)
|
||||
func (s *PoolServer) CreateOrUpdateCheckout(host string, id CartId) (*CheckoutOrder, error) {
|
||||
meta := &CheckoutMeta{
|
||||
Terms: fmt.Sprintf("https://%s/terms", r.Host),
|
||||
Checkout: fmt.Sprintf("https://%s/checkout?order_id={checkout.order.id}", r.Host),
|
||||
Confirmation: fmt.Sprintf("https://%s/confirmation/{checkout.order.id}", r.Host),
|
||||
Validation: fmt.Sprintf("https://%s/validate", r.Host),
|
||||
Push: fmt.Sprintf("https://%s/push?order_id={checkout.order.id}", r.Host),
|
||||
Country: getCountryFromHost(r.Host),
|
||||
Terms: fmt.Sprintf("https://%s/terms", host),
|
||||
Checkout: fmt.Sprintf("https://%s/checkout?order_id={checkout.order.id}", host),
|
||||
Confirmation: fmt.Sprintf("https://%s/confirmation/{checkout.order.id}", host),
|
||||
Validation: fmt.Sprintf("https://%s/validate", host),
|
||||
Push: fmt.Sprintf("https://%s/push?order_id={checkout.order.id}", host),
|
||||
Country: getCountryFromHost(host),
|
||||
}
|
||||
|
||||
// Get current grain state (may be local or remote)
|
||||
grain, err := s.pool.Get(id)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build pure checkout payload
|
||||
payload, _, err := BuildCheckoutOrderPayload(grain, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Call Klarna (create or update)
|
||||
var klarnaOrder *CheckoutOrder
|
||||
if grain.OrderReference != "" {
|
||||
klarnaOrder, err = KlarnaInstance.UpdateOrder(grain.OrderReference, bytes.NewReader(payload))
|
||||
return KlarnaInstance.UpdateOrder(grain.OrderReference, bytes.NewReader(payload))
|
||||
} else {
|
||||
klarnaOrder, err = KlarnaInstance.CreateOrder(bytes.NewReader(payload))
|
||||
return KlarnaInstance.CreateOrder(bytes.NewReader(payload))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PoolServer) ApplyCheckoutStarted(klarnaOrder *CheckoutOrder, id CartId) (*CartGrain, error) {
|
||||
// Persist initialization state via mutation (best-effort)
|
||||
return s.pool.Apply(id, &messages.InitializeCheckout{
|
||||
OrderId: klarnaOrder.ID,
|
||||
Status: klarnaOrder.Status,
|
||||
PaymentInProgress: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *PoolServer) HandleCheckout(w http.ResponseWriter, r *http.Request, id CartId) error {
|
||||
klarnaOrder, err := s.CreateOrUpdateCheckout(r.Host, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Persist initialization state via mutation (best-effort)
|
||||
if _, applyErr := s.pool.Apply(id, &messages.InitializeCheckout{
|
||||
OrderId: klarnaOrder.ID,
|
||||
Status: klarnaOrder.Status,
|
||||
PaymentInProgress: true,
|
||||
}); applyErr != nil {
|
||||
log.Printf("InitializeCheckout apply error: %v", applyErr)
|
||||
}
|
||||
s.ApplyCheckoutStarted(klarnaOrder, id)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
return json.NewEncoder(w).Encode(klarnaOrder)
|
||||
|
||||
Reference in New Issue
Block a user