Skip to content

Commit b73025e

Browse files
authored
[Framework] Add ingress cache (#70)
### **Motivation** Introduce efficient host+path resolution for DLX with O(logN) complexity, where `N = len(strings.Split(path, "/"))`. For full technical context, see [HLD](https://iguazio.atlassian.net/wiki/spaces/PLAT/pages/372080641/DLX+decoupling+ingress-nginx+annotations+HLD#Performance-tradeoffs) ### **Description** This PR lays the foundation for future ingress cache functionality, as described in the JIRA- https://iguazio.atlassian.net/browse/NUC-423 . Key deliverables include: - Initial cache DB structure - Thread-safe trie (`safeTrie`) for efficient path resolution - Unit tests validating DB operations and trie logic ### **Affected Areas** This is a standalone implementation with no impact on existing functionality. It introduces isolated, internal components to support upcoming features. ### **Testing** - Unit tests: cover all core cache logic and `pathTrie` interface implementations - Integration tests: to be addressed in a dedicated follow-up task ### **Changes Made** - Added `ingressCache.go` - implements `IngressHostCache`. - Added `safeTrie.go` - implements `IngressHostsTree`. ### **Additional Notes** - Additional in-memory optimizations for safeTrie are planned separately to keep this PR focused and scoped.
1 parent 0b8d4b7 commit b73025e

File tree

7 files changed

+1063
-0
lines changed

7 files changed

+1063
-0
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ require (
3535
github.com/pmezard/go-difflib v1.0.0 // indirect
3636
github.com/spf13/pflag v1.0.6 // indirect
3737
github.com/stretchr/objx v0.5.2 // indirect
38+
github.com/dghubble/trie v0.1.0 // indirect
3839
go.uber.org/multierr v1.11.0 // indirect
3940
go.uber.org/zap v1.27.0 // indirect
4041
golang.org/x/net v0.41.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
33
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
44
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
55
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
6+
github.com/dghubble/trie v0.1.0 h1:kJnjBLFFElBwS60N4tkPvnLhnpcDxbBjIulgI8CpNGM=
7+
github.com/dghubble/trie v0.1.0/go.mod h1:sOmnzfBNH7H92ow2292dDFWNsVQuh/izuD7otCYb1ak=
68
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
79
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
810
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=

pkg/ingresscache/ingresscache.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
Copyright 2025 Iguazio Systems Ltd.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License") with
5+
an addition restriction as set forth herein. You may not use this
6+
file except in compliance with the License. You may obtain a copy of
7+
the License at http://www.apache.org/licenses/LICENSE-2.0.
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12+
implied. See the License for the specific language governing
13+
permissions and limitations under the License.
14+
15+
In addition, you may not use the software for any purposes that are
16+
illegal under applicable law, and the grant of the foregoing license
17+
under the Apache 2.0 license is conditioned upon your compliance with
18+
such restriction.
19+
*/
20+
21+
package ingresscache
22+
23+
import (
24+
"sync"
25+
26+
"github.com/nuclio/errors"
27+
"github.com/nuclio/logger"
28+
)
29+
30+
type IngressCache struct {
31+
syncMap *sync.Map
32+
logger logger.Logger
33+
}
34+
35+
func NewIngressCache(logger logger.Logger) *IngressCache {
36+
return &IngressCache{
37+
syncMap: &sync.Map{},
38+
logger: logger,
39+
}
40+
}
41+
42+
func (ic *IngressCache) Set(host, path, function string) error {
43+
urlTree, exists := ic.syncMap.Load(host)
44+
if !exists {
45+
urlTree = NewSafeTrie()
46+
}
47+
48+
ingressHostsTree, ok := urlTree.(IngressHostsTree)
49+
if !ok {
50+
return errors.Errorf("cache set failed: invalid path tree value: got: %t", urlTree)
51+
}
52+
53+
if err := ingressHostsTree.SetFunctionName(path, function); err != nil {
54+
return errors.Wrap(err, "failed to set function name in the ingress host tree")
55+
}
56+
57+
if !exists {
58+
ic.syncMap.Store(host, urlTree)
59+
}
60+
return nil
61+
}
62+
63+
func (ic *IngressCache) Delete(host, path, function string) error {
64+
urlTree, exists := ic.syncMap.Load(host)
65+
if !exists {
66+
ic.logger.Debug("cache delete: host not found")
67+
return nil
68+
}
69+
70+
ingressHostsTree, ok := urlTree.(IngressHostsTree)
71+
if !ok {
72+
return errors.Errorf("cache delete failed: invalid path tree value: got: %t", urlTree)
73+
}
74+
75+
if err := ingressHostsTree.DeleteFunctionName(path, function); err != nil {
76+
return errors.Wrap(err, "failed to delete function name from the ingress host tree")
77+
}
78+
79+
if ingressHostsTree.IsEmpty() {
80+
// If the ingressHostsTree is empty after deletion, remove the host from the cache
81+
ic.syncMap.Delete(host)
82+
ic.logger.DebugWith("cache delete: host removed as it is empty",
83+
"host", host)
84+
}
85+
86+
return nil
87+
}
88+
89+
func (ic *IngressCache) Get(host, path string) ([]string, error) {
90+
urlTree, exists := ic.syncMap.Load(host)
91+
if !exists {
92+
return nil, errors.New("cache get failed: host does not exist")
93+
}
94+
95+
ingressHostsTree, ok := urlTree.(IngressHostsTree)
96+
if !ok {
97+
return nil, errors.Errorf("cache get failed: invalid path tree value: got: %t", urlTree)
98+
}
99+
100+
result, err := ingressHostsTree.GetFunctionNames(path)
101+
if err != nil {
102+
return nil, errors.Wrap(err, "failed to get the function name from the ingress host tree")
103+
}
104+
105+
return result, nil
106+
}

0 commit comments

Comments
 (0)