Skip to content
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

IWF-70: allow headers to be set in Interpreter Config #424

Merged
merged 8 commits into from
Oct 2, 2024

Conversation

samuel27m
Copy link
Member

@samuel27m samuel27m commented Sep 23, 2024

Closes #436

@samuel27m samuel27m marked this pull request as draft September 23, 2024 17:45
@@ -67,6 +67,7 @@ type IwfServiceTestConfig struct {
MemoEncryption bool
DisableFailAtMemoIncompatibility bool // default to false so that we will fail at test
OptimizedVersioning *bool
DefaultHeaders map[string]string
Copy link
Member Author

Choose a reason for hiding this comment

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

I saw that the previous implementation had integration tests that would check for the presence of the headers in every call, am I seeing that right? https://github.com/indeedeng/iwf/pull/356/files#diff-c3752f9aebfa9a670e62a5c0cc34c36bbfbfcbe849288ece0973806a34eac156R30-R33

I wanted to do something more flexible, where we would have a specific integration test for checking the headers passed in the configuration are being used, rather than having the route check it every time a call was made.

I do need some of your guidance here, I can't figure out how to do the integration tests with this approach.

Copy link
Contributor

Choose a reason for hiding this comment

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

The headers will be used when making calls for stateAPI. So for a specific integ tests, you will still need to build out a router. But it will be cleaner to have that specific router, is that what you meant?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's what I'm thinking yes. Do you think that would be overkill for testing such a small feature?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it’s a good idea. I have been lazy to do the right thing and the tests have become messy here

Copy link
Member Author

@samuel27m samuel27m Sep 25, 2024

Choose a reason for hiding this comment

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

I have created the tests now, I struggled a bit navigating through the existing ones trying to use one as a template. I'm sure the tests I created can be better. We can have a chat tomorrow about them and you can point me where I've gone wrong! Thanks in advance! 🙌

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good. I went through it and left you some comments already. and we can go through them later

@samuel27m
Copy link
Member Author

@longquanzheng If you have some time tomorrow, let's chat tomorrow about this PR. I do need some guidance on the integration tests in the comment above.

@samuel27m samuel27m marked this pull request as ready for review September 25, 2024 15:44
const (
WorkflowType = "basic"
State1 = "S1"
State2 = "S2"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: We can only have one state for this test

)

const (
WorkflowType = "basic"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: maybe "header"?

Comment on lines 42 to 44
if context.GetAttempt() <= 0 || context.GetFirstAttemptTimestamp() <= 0 {
panic("attempt and firstAttemptTimestamp should be greater than zero")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't have to check this

// start a workflow
sharedConfig := env.GetSharedConfig()
apiClient := iwfidl.NewAPIClient(&iwfidl.Configuration{
DefaultHeader: sharedConfig.Interpreter.InterpreterActivityConfig.DefaultHeader,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need this?

req := apiClient.DefaultApi.ApiV1WorkflowStartPost(context.Background())
startReq := iwfidl.WorkflowStartRequest{
WorkflowId: wfId,
IwfWorkflowType: basic.WorkflowType,
Copy link
Contributor

Choose a reason for hiding this comment

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

We should start the header workflow here

IwfWorkflowType: basic.WorkflowType,
WorkflowTimeoutSeconds: 100,
IwfWorkerUrl: "http://localhost:" + testWorkflowServerPort,
StartStateId: ptr.Any(basic.State1),
Copy link
Contributor

Choose a reason for hiding this comment

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

the starting state should be the header.State1

Comment on lines 88 to 114
WorkflowIDReusePolicy: ptr.Any(iwfidl.REJECT_DUPLICATE),
// TODO: need more work to write integ test for cron
// manual testing for now by uncomment the following line
// CronSchedule: iwfidl.PtrString("* * * * *"),
RetryPolicy: &iwfidl.WorkflowRetryPolicy{
InitialIntervalSeconds: iwfidl.PtrInt32(11),
BackoffCoefficient: iwfidl.PtrFloat32(11),
MaximumAttempts: iwfidl.PtrInt32(11),
MaximumIntervalSeconds: iwfidl.PtrInt32(11),
},
},
StateOptions: &iwfidl.WorkflowStateOptions{
StartApiTimeoutSeconds: iwfidl.PtrInt32(12),
DecideApiTimeoutSeconds: iwfidl.PtrInt32(13),
StartApiRetryPolicy: &iwfidl.RetryPolicy{
InitialIntervalSeconds: iwfidl.PtrInt32(12),
BackoffCoefficient: iwfidl.PtrFloat32(12),
MaximumAttempts: iwfidl.PtrInt32(12),
MaximumIntervalSeconds: iwfidl.PtrInt32(12),
},
DecideApiRetryPolicy: &iwfidl.RetryPolicy{
InitialIntervalSeconds: iwfidl.PtrInt32(13),
BackoffCoefficient: iwfidl.PtrFloat32(13),
MaximumAttempts: iwfidl.PtrInt32(13),
MaximumIntervalSeconds: iwfidl.PtrInt32(13),
},
},
Copy link
Contributor

Choose a reason for hiding this comment

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

we can skip all these

Comment on lines 133 to 150
resp2, httpResp, err := req2.WorkflowGetRequest(iwfidl.WorkflowGetRequest{
WorkflowId: wfId,
}).Execute()
panicAtHttpError(err, httpResp)

// use a wrong workflowId to test the error case
_, _, err = req2.WorkflowGetRequest(iwfidl.WorkflowGetRequest{
WorkflowId: "a wrong workflowId",
}).Execute()
apiErr, ok = err.(*iwfidl.GenericOpenAPIError)
if !ok {
log.Fatalf("Should fail to invoke get api %v", err)
}
errResp, ok = apiErr.Model().(iwfidl.ErrorResponse)
if !ok {
log.Fatalf("should be error response")
}
assertions.Equal(errResp.GetSubStatus(), iwfidl.WORKFLOW_NOT_EXISTS_SUB_STATUS)
Copy link
Contributor

Choose a reason for hiding this comment

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

we can skip these. So that the test is focusing on the header stuff only

@samuel27m
Copy link
Member Author

Thanks for all the test feedback @longquanzheng! This should be good to review now, let me know if there's something that you think I could simplify further! Thanks in advance! 🙌

config/config.go Outdated
@@ -68,6 +68,7 @@ type (
// default is http://localhost:ApiConfig.Port
ApiServiceAddress string `json:"serviceAddress"`
DumpWorkflowInternalActivityConfig *DumpWorkflowInternalActivityConfig `json:"dumpWorkflowInternalActivityConfig"`
DefaultHeader map[string]string `json:"defaultHeader"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Not: headers (plural)

Copy link
Member Author

Choose a reason for hiding this comment

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

Good eye! Thanks, fixed now 🙌

func (h *handler) ApiV1WorkflowStateStart(c *gin.Context) {
headerValue := c.GetHeader(TestHeaderKey)
if headerValue != TestHeaderValue {
c.JSON(http.StatusBadRequest, gin.H{"error": "test header not found"})
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to return here after c.JSON. Otherwise the remaining code will override it.

func (h *handler) ApiV1WorkflowStateDecide(c *gin.Context) {
headerValue := c.GetHeader(TestHeaderKey)
if headerValue != TestHeaderValue {
c.JSON(http.StatusBadRequest, gin.H{"error": "test header not found"})
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

if req.GetWorkflowType() == WorkflowType {
h.invokeHistory[req.GetWorkflowStateId()+"_decide"]++
if req.GetWorkflowStateId() == State1 {
// go to S2
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: wrong comment

config/config.go Outdated
@@ -68,6 +68,7 @@ type (
// default is http://localhost:ApiConfig.Port
ApiServiceAddress string `json:"serviceAddress"`
DumpWorkflowInternalActivityConfig *DumpWorkflowInternalActivityConfig `json:"dumpWorkflowInternalActivityConfig"`
DefaultHeaders map[string]string `json:"defaultHeader"`
Copy link
Contributor

Choose a reason for hiding this comment

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

json:"defaultHeaders"

Comment on lines 3 to 4
const TestHeaderKey = "integration-test-header"
const TestHeaderValue = "integration-test-value"
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: maybe constant.go? or just put it into routers.go

@samuel27m
Copy link
Member Author

Thanks for the comments! Should be all good now 👍

@longquanzheng
Copy link
Contributor

Thanks for the comments! Should be all good now 👍

Did you forget to push the changes m?

@samuel27m
Copy link
Member Author

samuel27m commented Sep 30, 2024

renaming things to be more accurate

I did push them here: af66ce5

Unless I forgot something ... 🤔

edit: i forgot to push the reset of the changes as you pointed out 😂 pushing now

@samuel27m
Copy link
Member Author

Ok, now it should be good 😂

@@ -0,0 +1 @@
package headers
Copy link
Contributor

Choose a reason for hiding this comment

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

Nite: we can remove it if it's empty

@samuel27m samuel27m changed the title allow headers to be set in Interpreter Config IWF-70: allow headers to be set in Interpreter Config Oct 2, 2024
@samuel27m samuel27m merged commit 5b4cefb into main Oct 2, 2024
6 checks passed
Copy link

codecov bot commented Oct 2, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 64.10%. Comparing base (a303990) to head (bb2ce57).
Report is 20 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #424      +/-   ##
==========================================
- Coverage   72.15%   64.10%   -8.06%     
==========================================
  Files          56       57       +1     
  Lines        5043     5937     +894     
==========================================
+ Hits         3639     3806     +167     
- Misses       1138     1866     +728     
+ Partials      266      265       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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.

Add configuration option to allow headers to be sent on requests from iwf-server to app worker
2 participants