mirror of
https://github.com/kevin-DL/services.git
synced 2026-01-15 04:24:44 +00:00
functions branch and region support (#330)
* branch and region support * . * . * . * . * fix functions * . * break loop * update example * update examples
This commit is contained in:
128
function/handler/reserve.go
Normal file
128
function/handler/reserve.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/micro/micro/v3/service/errors"
|
||||
"github.com/micro/micro/v3/service/store"
|
||||
pb "github.com/micro/services/function/proto"
|
||||
"github.com/micro/services/pkg/tenant"
|
||||
)
|
||||
|
||||
var (
|
||||
mtx sync.Mutex
|
||||
)
|
||||
|
||||
type Reservation struct {
|
||||
// The function name
|
||||
Name string `json:"name"`
|
||||
// The owner e.g tenant id
|
||||
Owner string `json:"owner"`
|
||||
// Uniq associated token
|
||||
Token string `json:"token"`
|
||||
// Time of creation
|
||||
Created time.Time `json:"created"`
|
||||
// The expiry time
|
||||
Expires time.Time `json:"expires"`
|
||||
}
|
||||
|
||||
func genToken(name, owner string) string {
|
||||
h := sha1.New()
|
||||
io.WriteString(h, name+owner)
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
||||
|
||||
// Call is a single request handler called via client.Call or the generated client code
|
||||
func (f *Function) Reserve(ctx context.Context, req *pb.ReserveRequest, rsp *pb.ReserveResponse) error {
|
||||
id, ok := tenant.FromContext(ctx)
|
||||
if !ok {
|
||||
id = "micro"
|
||||
}
|
||||
|
||||
if len(req.Name) == 0 {
|
||||
return errors.BadRequest("function.reserve", "missing function name")
|
||||
}
|
||||
|
||||
if len(req.Name) < 3 || len(req.Name) > 32 {
|
||||
return errors.BadRequest("function.reserve", "name must be longer than 3-32 chars in length")
|
||||
}
|
||||
|
||||
if !NameFormat.MatchString(req.Name) {
|
||||
return errors.BadRequest("function.reserve", "invalidate name format")
|
||||
}
|
||||
|
||||
// to prevent race conditions in reservation lets global lock
|
||||
mtx.Lock()
|
||||
defer mtx.Unlock()
|
||||
|
||||
// check the store for reservation
|
||||
recs, err := store.Read(ReservationKey + req.Name)
|
||||
if err != nil && err != store.ErrNotFound {
|
||||
return errors.InternalServerError("function.reserve", "failed to reserve name")
|
||||
}
|
||||
|
||||
var rsrv *Reservation
|
||||
|
||||
// check if the record exists
|
||||
if len(recs) > 0 {
|
||||
// existing reservation exists
|
||||
rec := recs[0]
|
||||
|
||||
if err := rec.Decode(&rsrv); err != nil {
|
||||
return errors.BadRequest("function.reserve", "name already reserved")
|
||||
}
|
||||
|
||||
// check the owner matches or if the reservation expired
|
||||
if rsrv.Owner != id && rsrv.Expires.After(time.Now()) {
|
||||
return errors.BadRequest("function.reserve", "name already reserved")
|
||||
}
|
||||
|
||||
// update the owner
|
||||
rsrv.Owner = id
|
||||
|
||||
// update the reservation expiry
|
||||
rsrv.Expires = time.Now().AddDate(1, 0, 0)
|
||||
} else {
|
||||
// check if its already running
|
||||
key := FunctionKey + req.Name
|
||||
recs, err := store.Read(key, store.ReadLimit(1))
|
||||
if err != nil && err != store.ErrNotFound {
|
||||
return errors.InternalServerError("function.reserve", "failed to reserve name")
|
||||
}
|
||||
|
||||
// existing function is running by that name
|
||||
if len(recs) > 0 {
|
||||
return errors.BadRequest("function.reserve", "function already exists")
|
||||
}
|
||||
|
||||
// not reserved
|
||||
rsrv = &Reservation{
|
||||
Name: req.Name,
|
||||
Owner: id,
|
||||
Created: time.Now(),
|
||||
Expires: time.Now().AddDate(1, 0, 0),
|
||||
Token: genToken(req.Name, id),
|
||||
}
|
||||
}
|
||||
|
||||
rec := store.NewRecord(ReservationKey+req.Name, rsrv)
|
||||
|
||||
if err := store.Write(rec); err != nil {
|
||||
return errors.InternalServerError("function.reserve", "error while reserving name")
|
||||
}
|
||||
|
||||
rsp.Reservation = &pb.Reservation{
|
||||
Name: rsrv.Name,
|
||||
Owner: rsrv.Owner,
|
||||
Created: rsrv.Created.Format(time.RFC3339Nano),
|
||||
Expires: rsrv.Expires.Format(time.RFC3339Nano),
|
||||
Token: rsrv.Token,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user