Skip to content

Conversation

weilerN
Copy link
Collaborator

@weilerN weilerN commented Jul 17, 2025

Description

This PR integrates the cache into the handler in order to resolve the request target based on the new cache.

Changes Made

  • Add the IngressHostCacheReader (the cache read-only access) to the handler
  • Add the logic for the new resolving (i.e. - try to resolve based on the cache, and if failed - resolve by the existing headers' logic)

Testing

  • Added a flow test - for the entire request handling
  • Added unit tests for the resolving per case (i.e. - based on headers and based on ingress)

References

Additional Notes

  • I left a TODO question inside the test file — it seems that when parsing the targetURL, the handler appends the path twice. This fix is relatively minor and has been tested manually, but since the current code still works, it's worth deciding whether we want to address it now.

@weilerN weilerN changed the title Nuc 523 integrate cache into request handler clean [Handler] Integrate the watcher's cache into request handler Jul 17, 2025
@weilerN weilerN requested a review from TomerShor July 17, 2025 14:20
@weilerN weilerN marked this pull request as ready for review July 17, 2025 14:25
@weilerN weilerN requested a review from rokatyy July 17, 2025 14:25
Copy link
Collaborator

@TomerShor TomerShor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, added some comments and suggestions

@@ -163,6 +166,43 @@ func (h *Handler) handleRequest(res http.ResponseWriter, req *http.Request) {
proxy.ServeHTTP(res, req)
}

func (h *Handler) getResourceNameAndPath(req *http.Request) (string, []string, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

align to the return order to make it clearer

Suggested change
func (h *Handler) getResourceNameAndPath(req *http.Request) (string, []string, error) {
func (h *Handler) getPathAndResourceNames(req *http.Request) (string, []string, error) {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return path, resourceNames, nil
}

func (h *Handler) extractValuesFromIngress(req *http.Request) (string, []string, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (h *Handler) extractValuesFromIngress(req *http.Request) (string, []string, error) {
func (h *Handler) getValuesFromCache(req *http.Request) (string, []string, error) {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return path, resourceNames, nil
}

h.logger.DebugWith("Failed to get target name from ingress cache, try to extract from the request headers",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
h.logger.DebugWith("Failed to get target name from ingress cache, try to extract from the request headers",
h.logger.DebugWith("Failed to get target from ingress cache, trying to extract from the request headers",

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path := req.URL.Path
resourceNames, err := h.ingressCache.Get(host, path)
if err != nil {
return "", nil, errors.New("Failed to get target name from ingress cache")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return "", nil, errors.New("Failed to get target name from ingress cache")
return "", nil, errors.New("Failed to get target names from ingress cache")

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 194 to 196
resourceNames, err := h.ingressCache.Get(host, path)
if err != nil {
return "", nil, errors.New("Failed to get target name from ingress cache")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mix resourceNames and target name in the variables and logs - choose one and stick with it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I’ll keep using resourceNames to stay consistent with the naming convention used in the handler context.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

func (suite *HandlerTestSuite) TestHandleRequest() {
for _, tc := range []struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for _, tc := range []struct {
for _, testCase := range []struct {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reqPath: "/test/path",
expectedStatus: http.StatusOK,
}, {
name: "No ingress headers,multiple targets found in ingress cache",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name: "No ingress headers,multiple targets found in ingress cache",
name: "No ingress headers, multiple targets found in ingress cache",

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

func (suite *HandlerTestSuite) TestGetResourceNameAndPath() {
for _, tc := range []struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for _, tc := range []struct {
for _, testCase := range []struct {

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 194 to 201
}, {
name: "Missing both ingress headers and host and path did not found in ingress cache",
reqHost: "www.example.com",
reqPath: "/test/path",
expectErr: true,
errMsg: "No target name header found",
},
} {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test case for existing both cache and headers - cache should take

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch of missing test case, adding

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 204 to 211
testIngressCache := ingresscache.NewIngressCache(suite.logger)
if tc.initialCachedData != nil {
err := testIngressCache.Set(tc.initialCachedData.host, tc.initialCachedData.path, tc.initialCachedData.targets)
suite.Require().NoError(err)
}

testHandler := suite.createTestHandler(suite.backendPort, testIngressCache)
testRequest := suite.createTestHTTPRequest(tc.reqHeaders, tc.reqHost, tc.reqPath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate from previous test - create a helper function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I replaced suite.createTestHandler with suite.createTestHandlerAndInitTestCache to reduce the duplication.
Refactoring the rest of the variables is a bit tedious, so I prefer to keep the test as-is for now.
Done here - CR comment - unit test comments

@weilerN weilerN requested a review from TomerShor July 20, 2025 12:53
path := req.URL.Path
resourceNames, err := h.ingressCache.Get(host, path)
if err != nil {
return "", nil, errors.New("Failed to get resourceNames from ingress cache")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return "", nil, errors.New("Failed to get resourceNames from ingress cache")
return "", nil, errors.New("Failed to get resource names from ingress cache")

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name string
resolveServiceNameErr error
initialCachedData *kube.IngressValue
reqHeaders map[string]string
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have no test case for existing request headers

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I didn't add coverage for the existing flow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expectedStatus int
}{
{
name: "No ingress headers, host and path found in ingress cache",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name: "No ingress headers, host and path found in ingress cache",
name: "No request headers, host and path found in ingress cache",

Same comment for all test case names

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expectedResourceNames []string
}{
{
name: "No ingress headers, host and path found in ingress cache",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the cases in this test:

Suggested change
name: "No ingress headers, host and path found in ingress cache",
name: "No request headers, host and path found in ingress cache",

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h.logger.WarnWith("Failed to get resource names and path from request",
"error", err.Error(),
"host", req.Host,
"path", req.URL.Path)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that req.URL is pointer, so might technically be nil, do we check it anywhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I will cover it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weilerN weilerN requested review from TomerShor and rokatyy July 21, 2025 09:15
@TomerShor TomerShor merged commit 925df2c into v3io:development Jul 21, 2025
3 checks passed
rokatyy added a commit to nuclio/nuclio that referenced this pull request Jul 21, 2025
### Description  
This PR integrates the new DLX from the Scaler package, which introduces
a revised internal flow.
The changes align the DLX initialization with the new Scaler
initialization and configuration patterns by updating the `dlxOptions`
and related logic.

### Changes Made  
- Extracted hardcoded configuration variables
- Implemented the `scalertype.ResolveTargetsFromIngressCallback` for
extracting Nuclio targets
- Added changes to the DLX init (as described in the Jira)

### Testing  
- Unit tests for the new `resolveCallback`
- Manual integration tests to verify the functionalities
 
### References  
- Jira ticket link  - https://iguazio.atlassian.net/browse/NUC-509
- External links - the related scaler PRs
-- v3io/scaler#76 
-- v3io/scaler#78

### Additional Notes  
- Before merging this PR, the `go.mod` must be modified since it
currently relies on a feature branch

---------

Co-authored-by: Katerina Molchanova <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants