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
Activation id in header #3671
Activation id in header #3671
Conversation
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.
Rather than add new tests, how about adding a header check to existing tests for invokes, and triggers.
|
||
respondWithActivationIdHeader(activationId) { | ||
// note that if header defined a content-type, it will be ignored | ||
// since the type must be compatible with the data response |
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.
I don’t think this comment makes sense here.
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.
removed.
@@ -634,37 +634,40 @@ trait WhiskWebActionsApi extends Directives with ValidateRequestSize with PostAc | |||
responseType: MediaExtension)(implicit transid: TransactionId) = { | |||
onComplete(queuedActivation) { | |||
case Success(Right(activation)) => | |||
val result = activation.resultAsJson | |||
respondWithActivationIdHeader(activation) { |
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.
I do not think the activation id should be reported in webaction. It leaks information. For normal POSTS it is ok because there’s an explicit subject key. For webactions, there is not.
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.
This is to cope with the inconvenience which is described in #3582.
This will give users a better option to retrieve right activation results.
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.
A webaction is called by an anonymous subject. The activation id is information specific to the subject owning the action.
The webaction can return its own header to identify the action; which could be the activation id if it chooses - I do not think the system should blanket return the activation id for webactions.
e12a51e
to
10e3028
Compare
@rabbah |
protected trait CustomHeaders extends Directives { | ||
|
||
/** Add activation ID in headers */ | ||
protected def respondWithActivationIdHeader(activation: WhiskActivation): Directive0 = |
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.
Do we need to override this method?
Wouldn't it be easier to always pass the activationId? You have it anyway, if you have the activation.
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.
Updated accordingly
@@ -91,6 +91,8 @@ protected trait ControllerTestCommon | |||
val authStore = WhiskAuthStore.datastore() | |||
val logStore = SpiLoader.get[LogStoreProvider].logStore(actorSystem) | |||
|
|||
val ActivationIdHeaderInLowercase = "x-openwhisk-activation-id" |
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.
Can you move this variable to CustomHeaders
and use it here as well? (And start with a lowercase letter)
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.
Updated accordingly.
Regarding case, I followed scala constant naming convention(Upper camel case).
Is it OW convention(start with a lowercase letter)?
Given that the API Gateway sets the |
@ddragosd the request id isn't the activation id though --- although I raised the question in the related issue: should the two be the same in which case, the gateway or nginx generates the id and adds the header on the response. |
Any reason they can't be the same ? |
activation id needs to be unique to a namespace since it serves as part of the document id stored in the activation store (for metadata etc)... if that's satisfied i think we can do it. |
makes sense @rabbah . I'd say we can safely assume that the Gateway generates unique activation IDs. |
10e3028
to
ae4f98f
Compare
@rabbah @ddragosd
But maybe there is an easy solution for all of these concerns ;) |
Codecov Report
@@ Coverage Diff @@
## master #3671 +/- ##
==========================================
- Coverage 85.43% 80.75% -4.68%
==========================================
Files 147 147
Lines 7070 7077 +7
Branches 423 423
==========================================
- Hits 6040 5715 -325
- Misses 1030 1362 +332
Continue to review full report at Codecov.
|
For the first parts: For a trigger, the request id is the triggers activation id. Every activated action generates a new activation id as we do today. For a sequence the outermost action (the sequence itself) gets the id all the subcomponents get new ids (as today). Same for conductor actions. The uniqueness is the part I’m concerned about. |
Let me recap the intermediate conclusion.
Regarding 1, I initially raised this issue in the aspect of UI. When providing the functionality to display activation results and logs after an invocation of an action in UI, it's not easy to select right activation when the action is webaction. In case of normal action also, since activation logs are collected asynchronously, it's not that simple. For webactions, it's not easy to choose a specific activation, and display logs for web actions without system support. Any suggestions for this? With regard to 2, so request ID would be Transaction ID and Activation ID. I just want to confirm. |
@cbickel does #3671 (comment) address your concerns? if we adopt the nginx generated id as the activation id, then this pr becomes a lot simpler. |
@rabbah |
@@ -1043,13 +1043,15 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi { | |||
status should be(Accepted) | |||
val response = responseAs[JsObject] | |||
response.fields("activationId") should not be None | |||
headers.exists(_.is(ActivationIdHeaderInLowercase)) should be(true) |
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.
headers are immutable and per the line above you know the correct activation id. You should be able to rewrite this to something like:
headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String]))
That'll give you a more explanatory response in tests. WDYT?
headers.exists(header => { | ||
header.is("set-cookie") && header.value() == "a=b" | ||
}) shouldBe true | ||
headers.exists(_.is(ActivationIdHeaderInLowercase)) shouldBe true |
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.
See comment above, please rewrite both of these into "contains" checks.
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.
got it
} | ||
|
||
// repeat invoke, get only result back | ||
Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> Route.seal(routes(creds)) ~> check { | ||
headers |
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.
bad push?
Is there something actionable in here? Should we take the discussion out to the dev-list? At least the bit on generating activationIds from something outside of the controller seems worth discussing in a broader audience. |
I think the point is, if we allow activationID generation in multiple components(nginx, controller), we cannot guarantee the activationID is unique(though the possibility of duplicate activationID is less.) To use the same ID for |
@rabbah |
I think I've changed perspective on the activation id in the header response of web actions, after some further consideration (to agree with you, and that it's OK). I can explain in a longer comment later if necessary. |
How about separating ActivationID addition in headers and using same ID for How about taking these changes and discussing the second one in dev-list or another PR separately? |
ae4f98f
to
1ce7b2f
Compare
1ce7b2f
to
187992d
Compare
} | ||
|
||
// repeat this time wait longer than active ack delay | ||
Post(s"$collectionPath/${action.name}?blocking=true&timeout=500") ~> Route.seal(routes(creds)) ~> check { | ||
status shouldBe OK | ||
val response = responseAs[JsObject] | ||
response shouldBe activation.withoutLogs.toExtendedJson | ||
headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String])) | ||
|
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.
Extra line.
@@ -1319,6 +1329,8 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi { | |||
status should be(InternalServerError) | |||
val response = responseAs[JsObject] | |||
response should be(activation.withoutLogs.toExtendedJson) | |||
headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String])) | |||
|
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.
Extra line.
@@ -89,6 +89,8 @@ protected trait ControllerTestCommon | |||
val logStore = SpiLoader.get[LogStoreProvider].instance(actorSystem) | |||
val activationStore = SpiLoader.get[ActivationStoreProvider].instance(actorSystem, materializer, logging) | |||
|
|||
val ActivationIdHeaderInLowercase = ActivationIdHeader.toLowerCase | |||
|
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.
Is this used?
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.
I think it would be better to keep it because I restored the previous exist
logic.
Unlike a normal action, we are unable to get the value of ActivationID
from the response as so unable to use contain
logic that Markus suggested.
headers should contain(RawHeader(ActivationIdHeader, _)) // does not work
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.
I'd propose to make the global setting lowercased then, and use that throughout. WDYT?
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.
Sorry, what is the global setting?
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.
The value in CustomHeaders
?
6d83f8d
to
8d9608e
Compare
Travis build has passed. |
152c29f
to
19e64fc
Compare
Updated accordingly |
@@ -65,15 +65,24 @@ protected[controller] trait ValidateRequestSize extends Directives { | |||
protected val fieldDescriptionForSizeError = "Request" | |||
} | |||
|
|||
protected trait CustomHeaders extends Directives { | |||
val ActivationIdHeader = "x-openwhisk-activation-id" |
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.
I think @mhenke1 introduced a header with X-OW as the prefix. API gateway uses x-openwhisk. We should normalize and collocate these. Fwiw nginx also generates x-request-id header.
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.
@rabbah Agree.
How about using x-openwhisk?
Since x- header is a custom header specific to the application, it would be better to use the detailed one.
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.
I am not sure changes to use the same OpenWhisk prefix for all custom headers should be included in this PR.
19e64fc
to
ec20733
Compare
Any comments on this? |
I think we should still pursue id consolidation - I don't think we need both an activation id and a transaction id for top level activations, and we should further then reduce the number of headers we're communicating back (it would just be one id that means both). Deferring to another discussion/PR. |
I used this today. 💪 |
Sounds great to me :) |
This closes #3582
Description
This change will add activation id in the response headers.
Since same logic needs to be used in both collection API and web action API, I created dedicated trait for custom headers.
Related issue and scope
My changes affect the following components
Types of changes
Checklist: