func (item *Item) Ship(user string, qty uint64, timestamp string) (*Shipment, bool, error) { // Create a reproducible ID based on input data (hence the timestamp) hash := services.MakeHash(user, item.Name, qty, timestamp) shipment := item.catalog.MakeShipment(hash) if err := shipment.lock.Lock(); err != nil { return nil, false, fmt.Errorf("Failed to lock shipment: %v", err) } defer shipment.unlock() existed, err := shipment.LoadExisting() if err != nil { return nil, false, err } if !existed { shipment.User = user shipment.Item = item.Name shipment.Quantity = qty shipment.Status = catalogApi.ShipmentCreated if err = shipment.Save(); err != nil { return nil, false, err } } return shipment, existed, nil }
func (payments *Payments) NewPayment(username string, value float64, timestamp string) (*Payment, bool, error) { // Create a reproducible ID based on input data (hence the timestamp) hash := services.MakeHash(username, value, timestamp) // Try to fetch an existing payment payment := payments.MakePayment(hash) existed, err := payment.LoadExisting(true, false) if err != nil { return nil, false, err } defer payment.unlock() // Create the payment, if it did not exist if !existed { payment.User = username payment.Value = value payment.TransactionId = "" payment.setStatus(PaymentCreated) if err = payment.Save(); err != nil { return nil, false, err } } // Now try to create the remote transaction if err = payment.advance(PaymentPending); err != nil { return nil, false, err } else { return payment, existed, nil } }
func (shop *Shop) noteFreshOrder(username string, item string, qty uint64) error { hash := services.MakeHash(username, item, qty) resp := shop.redis.Cmd("set", fresh_orders_key+hash, shop.redisLockValue, "ex", fresh_order_timeout_sec, "nx") if err := resp.Err(); err != nil { return err } if str, _ := resp.Str(); resp.HasResult() && str == "OK" { return nil } else { // The same order has been submitted within fresh_order_timeout return fmt.Errorf("Order rejected: duplicate order suspected") } }