|
1 | 1 | package function |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "encoding/json" |
| 4 | + "context" |
5 | 5 | "fmt" |
6 | | - |
7 | 6 | "time" |
8 | | - |
9 | | - "github.com/serverledge-faas/serverledge/internal/cache" |
10 | | - "github.com/serverledge-faas/serverledge/utils" |
11 | | - clientv3 "go.etcd.io/etcd/client/v3" |
12 | | - "golang.org/x/net/context" |
13 | 7 | ) |
14 | 8 |
|
15 | | -// Function describes a serverless function. |
16 | | -type Function struct { |
17 | | - Name string |
18 | | - Runtime string // example: python310 |
19 | | - MemoryMB int64 // MB |
20 | | - CPUDemand float64 // 1.0 -> 1 core |
21 | | - Handler string // example: "module.function_name" |
22 | | - TarFunctionCode string // input is .tar |
23 | | - CustomImage string // used if custom runtime is chosen |
24 | | - Signature *Signature |
25 | | -} |
26 | | - |
27 | | -func (f *Function) getEtcdKey() string { |
28 | | - return getEtcdKey(f.Name) |
29 | | -} |
30 | | - |
31 | | -func getEtcdKey(funcName string) string { |
32 | | - return fmt.Sprintf("/function/%s", funcName) |
33 | | -} |
34 | | - |
35 | | -// GetFunction retrieves a Function given its name. If it doesn't exist, returns false |
36 | | -func GetFunction(name string) (*Function, bool) { |
37 | | - |
38 | | - val, found := getFromCache(name) |
39 | | - if !found { |
40 | | - // cache miss |
41 | | - f, response := getFromEtcd(name) |
42 | | - if !response { |
43 | | - return nil, false |
44 | | - } |
45 | | - //insert a new element to the cache |
46 | | - cache.GetCacheInstance().Set(name, f, cache.DefaultExp) |
47 | | - return f, true |
48 | | - } |
49 | | - |
50 | | - return val, true |
51 | | - |
52 | | -} |
53 | | - |
54 | | -func (f *Function) String() string { |
55 | | - return f.Name |
56 | | -} |
57 | | - |
58 | | -func getFromCache(name string) (*Function, bool) { |
59 | | - localCache := cache.GetCacheInstance() |
60 | | - f, found := localCache.Get(name) |
61 | | - if !found { |
62 | | - return nil, false |
63 | | - } |
64 | | - //cache hit |
65 | | - //return a safe copy of the function previously obtained |
66 | | - function := *f.(*Function) |
67 | | - return &function, true |
68 | | - |
| 9 | +// Request represents a single function invocation, with a ReqId, reference to the Function, parameters and metrics data |
| 10 | +type Request struct { |
| 11 | + Ctx context.Context |
| 12 | + Fun *Function |
| 13 | + Params map[string]interface{} |
| 14 | + Arrival time.Time |
| 15 | + RequestQoS |
| 16 | + CanDoOffloading bool |
| 17 | + Async bool |
| 18 | + ReturnOutput bool |
69 | 19 | } |
70 | 20 |
|
71 | | -func getFromEtcd(name string) (*Function, bool) { |
72 | | - cli, err := utils.GetEtcdClient() |
73 | | - if err != nil { |
74 | | - return nil, false |
75 | | - } |
76 | | - ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) |
77 | | - getResponse, err := cli.Get(ctx, getEtcdKey(name)) |
78 | | - if err != nil || len(getResponse.Kvs) < 1 { |
79 | | - return nil, false |
80 | | - } |
81 | | - |
82 | | - var f Function |
83 | | - err = json.Unmarshal(getResponse.Kvs[0].Value, &f) |
84 | | - if err != nil { |
85 | | - return nil, false |
86 | | - } |
87 | | - |
88 | | - return &f, true |
| 21 | +type RequestQoS struct { |
| 22 | + Class ServiceClass |
| 23 | + MaxRespT float64 |
89 | 24 | } |
90 | 25 |
|
91 | | -// SaveToEtcd registers the function to Etcd |
92 | | -func (f *Function) SaveToEtcd() error { |
93 | | - cli, err := utils.GetEtcdClient() |
94 | | - if err != nil { |
95 | | - return err |
96 | | - } |
97 | | - ctx := context.TODO() |
98 | | - |
99 | | - payload, err := json.Marshal(*f) |
100 | | - if err != nil { |
101 | | - return fmt.Errorf("Could not marshal function: %v", err) |
102 | | - } |
103 | | - _, err = cli.Put(ctx, f.getEtcdKey(), string(payload)) |
104 | | - if err != nil { |
105 | | - return fmt.Errorf("Failed Put: %v", err) |
106 | | - } |
107 | | - |
108 | | - // Add the function to the local cache |
109 | | - cache.GetCacheInstance().Set(f.Name, f, cache.DefaultExp) |
110 | | - |
111 | | - return nil |
| 26 | +type ExecutionReport struct { |
| 27 | + Result string |
| 28 | + ResponseTime float64 // time waited by the user to get the output: completion time - arrival time (offload + cold start + execution time) |
| 29 | + IsWarmStart bool |
| 30 | + InitTime float64 // time spent sleeping before initializing container |
| 31 | + OffloadLatency float64 // time spent offloading the request |
| 32 | + Duration float64 // execution (service) time |
| 33 | + SchedAction string |
| 34 | + Output string |
112 | 35 | } |
113 | 36 |
|
114 | | -// Delete removes a function from Etcd and the local cache. |
115 | | -func (f *Function) Delete() error { |
116 | | - cli, err := utils.GetEtcdClient() |
117 | | - if err != nil { |
118 | | - return err |
119 | | - } |
120 | | - ctx := context.TODO() |
121 | | - |
122 | | - dresp, err := cli.Delete(ctx, f.getEtcdKey()) |
123 | | - if err != nil { |
124 | | - return fmt.Errorf("Failed Delete: %v", err) |
125 | | - } else if dresp.Deleted != 1 { |
126 | | - fmt.Printf("no function with key '%s' exists", f.getEtcdKey()) |
127 | | - } |
128 | | - |
129 | | - // Remove the function from the local cache |
130 | | - cache.GetCacheInstance().Delete(f.Name) |
131 | | - |
132 | | - return nil |
| 37 | +type Response struct { |
| 38 | + Success bool |
| 39 | + ExecutionReport |
133 | 40 | } |
134 | 41 |
|
135 | | -func (f *Function) Equals(f2 *Function) bool { |
136 | | - return (f == nil && f2 == nil) || (f.Name == f2.Name && |
137 | | - f.CustomImage == f2.CustomImage && |
138 | | - f.CPUDemand == f2.CPUDemand && |
139 | | - f.Runtime == f2.Runtime && |
140 | | - f.Handler == f2.Handler && |
141 | | - f.MemoryMB == f2.MemoryMB && |
142 | | - f.TarFunctionCode == f2.TarFunctionCode) |
| 42 | +type AsyncResponse struct { |
| 43 | + ReqId string |
143 | 44 | } |
144 | 45 |
|
145 | | -// Exists checks if the function is already saved to Etcd |
146 | | -func (f *Function) Exists() bool { |
147 | | - savedFunction, ok := GetFunction(f.Name) |
148 | | - return ok && f.Equals(savedFunction) |
| 46 | +func (r *Request) Id() string { |
| 47 | + return r.Ctx.Value("ReqId").(string) |
149 | 48 | } |
150 | 49 |
|
151 | | -// GetAll returns all function names |
152 | | -func GetAll() ([]string, error) { |
153 | | - return GetAllWithPrefix("/function") |
| 50 | +func (r *Request) String() string { |
| 51 | + return fmt.Sprintf("[%s] Rq-%s", r.Fun.Name, r.Id()) |
154 | 52 | } |
155 | 53 |
|
156 | | -// GetAllWithPrefix is used to get all /function or /workflow currently registered in etcd |
157 | | -func GetAllWithPrefix(prefix string) ([]string, error) { |
158 | | - cli, err := utils.GetEtcdClient() |
159 | | - if err != nil { |
160 | | - return nil, err |
161 | | - } |
162 | | - ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Second) |
163 | | - defer cancel() |
164 | | - |
165 | | - resp, err := cli.Get(ctx, prefix, clientv3.WithPrefix()) |
166 | | - if err != nil { |
167 | | - return nil, err |
168 | | - } |
| 54 | +type ServiceClass int64 |
169 | 55 |
|
170 | | - functions := make([]string, len(resp.Kvs)) |
171 | | - for i, s := range resp.Kvs { |
172 | | - functions[i] = string(s.Key)[len(prefix+"/"):] |
173 | | - } |
174 | | - |
175 | | - return functions, ctx.Err() |
176 | | -} |
| 56 | +const ( |
| 57 | + LOW ServiceClass = 0 |
| 58 | + HIGH_PERFORMANCE = 1 |
| 59 | + HIGH_AVAILABILITY = 2 |
| 60 | +) |
0 commit comments