-
Notifications
You must be signed in to change notification settings - Fork 14
[Framework] Improve saferTrie node's value #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
2e952e9
dff469f
786fca4
e168a5f
0f1c127
5a0a141
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,7 +21,6 @@ such restriction. | |||||||||
| package ingresscache | ||||||||||
|
|
||||||||||
| import ( | ||||||||||
| "slices" | ||||||||||
| "sync" | ||||||||||
|
|
||||||||||
| "github.com/dghubble/trie" | ||||||||||
|
|
@@ -41,8 +40,8 @@ func NewSafeTrie() *SafeTrie { | |||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // SetFunctionName sets a function for a given path. If the path does not exist, it creates it | ||||||||||
| func (st *SafeTrie) SetFunctionName(path string, function string) error { | ||||||||||
| // Set adds a function for a given path. If the path does not exist, it creates it | ||||||||||
| func (st *SafeTrie) Set(path string, function string) error { | ||||||||||
| if path == "" { | ||||||||||
| return errors.New("path is empty") | ||||||||||
| } | ||||||||||
|
|
@@ -57,28 +56,31 @@ func (st *SafeTrie) SetFunctionName(path string, function string) error { | |||||||||
| // get the exact path value in order to avoid creating a new path if it already exists | ||||||||||
| pathValue := st.pathTrie.Get(path) | ||||||||||
| if pathValue == nil { | ||||||||||
| st.pathTrie.Put(path, []string{function}) | ||||||||||
| st.pathTrie.Put(path, &SingleTarget{function}) | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| pathFunctionNames, ok := pathValue.([]string) | ||||||||||
| pathFunctionNames, ok := pathValue.(FunctionTarget) | ||||||||||
| if !ok { | ||||||||||
| return errors.Errorf("path value should be []string, got %T", pathValue) | ||||||||||
| return errors.Errorf("path value should be FunctionTarget, got %T", pathValue) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if slices.Contains(pathFunctionNames, function) { | ||||||||||
| if pathFunctionNames.Contains(function) { | ||||||||||
| // If the function already exists at this path, skip adding it to prevent duplicates | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| pathFunctionNames = append(pathFunctionNames, function) | ||||||||||
| st.pathTrie.Put(path, pathFunctionNames) | ||||||||||
| functionNames, err := pathFunctionNames.Add(function) | ||||||||||
| if err != nil { | ||||||||||
| return errors.Wrapf(err, "failed to set function name to path. path: %s, function: %s", path, function) | ||||||||||
| } | ||||||||||
| st.pathTrie.Put(path, functionNames) | ||||||||||
|
|
||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // DeleteFunctionName removes a function from a path and also deletes the path if the function is the only one associated with that path | ||||||||||
| func (st *SafeTrie) DeleteFunctionName(path string, function string) error { | ||||||||||
| // Delete removes a function from a path and also deletes the path if the function is the only one associated with that path | ||||||||||
| func (st *SafeTrie) Delete(path string, function string) error { | ||||||||||
| st.rwMutex.Lock() | ||||||||||
| defer st.rwMutex.Unlock() | ||||||||||
|
|
||||||||||
|
|
@@ -88,27 +90,30 @@ func (st *SafeTrie) DeleteFunctionName(path string, function string) error { | |||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| pathFunctionNames, ok := pathValue.([]string) | ||||||||||
| pathFunctionNames, ok := pathValue.(FunctionTarget) | ||||||||||
| if !ok { | ||||||||||
| return errors.Errorf("path value should be []string, got %T", pathValue) | ||||||||||
| return errors.Errorf("path value should be FunctionTarget, got %T", pathValue) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // If the function to delete matches the current function name and it's the only value, delete the path | ||||||||||
| if len(pathFunctionNames) == 1 { | ||||||||||
| if pathFunctionNames[0] == function { | ||||||||||
| // If the function to delete matches the current function name, and it's the only value, delete the path | ||||||||||
| if pathFunctionNames.IsSingle() { | ||||||||||
| if pathFunctionNames.Contains(function) { | ||||||||||
| st.pathTrie.Delete(path) | ||||||||||
| } | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // TODO - will be removed once moving into efficient pathFunctionNames implementation (i.e. not using slices) | ||||||||||
| pathFunctionNames = excludeElemFromSlice(pathFunctionNames, function) | ||||||||||
| st.pathTrie.Put(path, pathFunctionNames) | ||||||||||
| // update the path with the new function names after deletion | ||||||||||
| functionNames, err := pathFunctionNames.Delete(function) | ||||||||||
| if err != nil { | ||||||||||
| return errors.Wrapf(err, "failed to remove function name from path. function: %s, path: %s", function, path) | ||||||||||
| } | ||||||||||
| st.pathTrie.Put(path, functionNames) | ||||||||||
| return nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // GetFunctionNames retrieve the closest prefix matching the path and returns the associated functions | ||||||||||
| func (st *SafeTrie) GetFunctionNames(path string) ([]string, error) { | ||||||||||
| // Get retrieve the closest prefix matching the path and returns the associated functions | ||||||||||
| func (st *SafeTrie) Get(path string) (FunctionTarget, error) { | ||||||||||
| var walkPathResult interface{} | ||||||||||
| if path == "" { | ||||||||||
| return nil, errors.New("path is empty") | ||||||||||
|
|
@@ -127,9 +132,9 @@ func (st *SafeTrie) GetFunctionNames(path string) ([]string, error) { | |||||||||
| return nil, errors.Errorf("no value found for path: %s", path) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| functionNames, ok := walkPathResult.([]string) | ||||||||||
| functionNames, ok := walkPathResult.(FunctionTarget) | ||||||||||
| if !ok { | ||||||||||
| return nil, errors.Errorf("walkPathResult value should be []string, got %v", walkPathResult) | ||||||||||
| return nil, errors.Errorf("walkPathResult value should be FunctionTarget, got %v", walkPathResult) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return functionNames, nil | ||||||||||
|
|
@@ -146,25 +151,77 @@ func (st *SafeTrie) IsEmpty() bool { | |||||||||
| return walkResult == nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // TODO - will be removed once moving into efficient pathFunctionNames implementation (i.e. not using slices) | ||||||||||
| func excludeElemFromSlice(slice []string, elem string) []string { | ||||||||||
| // Assuming len(slice) <= 2 based on the ingress validations of: https://github.com/nuclio/nuclio/pkg/platform/kube/platform.go | ||||||||||
| switch len(slice) { | ||||||||||
| case 1: | ||||||||||
| if slice[0] == elem { | ||||||||||
| return []string{} | ||||||||||
| } | ||||||||||
| return slice | ||||||||||
| case 2: | ||||||||||
| if slice[0] == elem { | ||||||||||
| return []string{slice[1]} | ||||||||||
| } | ||||||||||
| if slice[1] == elem { | ||||||||||
| return []string{slice[0]} | ||||||||||
| } | ||||||||||
| // elem not found, return original slice | ||||||||||
| return slice | ||||||||||
| default: | ||||||||||
| return slice | ||||||||||
| // ----- implementations for FunctionTarget interface ----- | ||||||||||
|
|
||||||||||
| type SingleTarget struct { | ||||||||||
| functionName string | ||||||||||
| } | ||||||||||
|
||||||||||
| type SingleTarget struct { | |
| functionName string | |
| } | |
| type SingleTarget string |
If we're talking about optimization, what is the difference between the two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, fixed here - CR comment-change singleTarget from struct to a string wrapper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed anymore, part of
AddanywayThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done here- CR comment- rephrase comments