-
Notifications
You must be signed in to change notification settings - Fork 393
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
Convert say, ack, and respond to return promises #369
Conversation
@@ -29,7 +29,7 @@ | |||
"build": "tsc", | |||
"build:clean": "shx rm -rf ./dist ./coverage ./.nyc_output", | |||
"lint": "tslint --project .", | |||
"test-lint": "tslint \"src/**/*.spec.ts\" && tslint \"src/test-helpers.ts\"", | |||
"test-lint": "tslint --project tsconfig.test.json \"src/**/*.spec.ts\" && tslint --project tsconfig.test.json \"src/test-helpers.ts\"", |
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 wanted to be able to lint the test cases for proper async handling, that requires types in tslint, so I made a config specifically for test.
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.
👍
src/App.ts
Outdated
const postMessageArguments: ChatPostMessageArguments = (typeof message === 'string') ? | ||
{ token, text: message, channel: channelId } : { ...message, token, channel: channelId }; | ||
this.client.chat.postMessage(postMessageArguments) | ||
return this.client.chat.postMessage(postMessageArguments) |
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 thought this made more sense resolving the result of this call rather than void
.
Enables folks who want to the ability to get things like the ts
off the result for later updating.
Codecov Report
@@ Coverage Diff @@
## master #369 +/- ##
==========================================
+ Coverage 83.29% 83.56% +0.26%
==========================================
Files 7 7
Lines 497 505 +8
Branches 143 145 +2
==========================================
+ Hits 414 422 +8
Misses 54 54
Partials 29 29
Continue to review full report at Codecov.
|
@@ -82,7 +82,7 @@ export default class ExpressReceiver extends EventEmitter implements Receiver { | |||
); | |||
const event: ReceiverEvent = { | |||
body: req.body as { [key: string]: any }, | |||
ack: (response: any): void => { | |||
ack: async (response: any): Promise<void> => { |
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.
Express's res.send
is actually synchronous and won't ever error. I believe this still makes sense to force the signature to a promise for other types of receivers.
src/ExpressReceiver.ts
Outdated
this.emit('error', e); | ||
}); | ||
event.respond = async (response) => { | ||
await this.axios.post(req.body.response_url, 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 removed the catch
so this will behave more like promises would expect. Left unchecked in the new middleware pattern, it will be bubbled up to the global error handler anyway I figured this was safe and more expected.
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.
Update: I'm going to update this pr to move this block into onIncommingEvent so that every receiver doesn't need to implement it.
Incoming shortly.
// it’s a valid email, accept the submission | ||
if (isEmail.test(action.submission.email)) { | ||
ack(); | ||
await ack(); | ||
} else { | ||
// if it isn’t a valid email, acknowledge with an error | ||
ack({ |
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.
nit: Is it intentional not to have await
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.
🤦♂ Not a nit, great catch. After missing this, I took another pass searching for these and updated a few more 🎉
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.
If only we could lint js inside markdown.
// メールアドレスが有効。ダイアログを受信 | ||
if (isEmail.test(action.submission.email)) { | ||
ack(); | ||
await ack(); | ||
} else { | ||
// メールアドレスが無効。エラーを確認 | ||
ack({ |
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.
(same as above)
@@ -29,7 +29,7 @@ | |||
"build": "tsc", | |||
"build:clean": "shx rm -rf ./dist ./coverage ./.nyc_output", | |||
"lint": "tslint --project .", | |||
"test-lint": "tslint \"src/**/*.spec.ts\" && tslint \"src/test-helpers.ts\"", | |||
"test-lint": "tslint --project tsconfig.test.json \"src/**/*.spec.ts\" && tslint --project tsconfig.test.json \"src/test-helpers.ts\"", |
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.
👍
src/App.ts
Outdated
@@ -400,10 +418,10 @@ export default class App { | |||
// Factory for say() utility | |||
const createSay = (channelId: string): SayFn => { | |||
const token = context.botToken !== undefined ? context.botToken : context.userToken; | |||
return (message: Parameters<SayFn>[0]) => { | |||
return (message: Parameters<SayFn>[0]): Promise<void | WebAPICallResult> => { |
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'm still thinking but it may be better to return Promise<WebAPICallResult | CodedError>
here even after applying onGlobalError
. Any thoughts?
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 clearly wasn't thinking straight here, I removed the global error handler as it will be called anyway if this goes uncaught.
This means that this returns what chat.postMessage
is which is simply Promise<WebAPICallResult>
I just checked on CodedError, looks cool, I would think the right thing to do would be to update @slack/web-api
to handle that rather than bolt. That way you have a consistent api between say
and client.chat.postMessage
What do you think?
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.
🙏 for the late reply here: I agree that we can remove the global error handler here to be consistent with others such as app.client
calls and respond
👍
src/App.ts
Outdated
listenerArgs.respond = respond; | ||
if (body.response_url) { | ||
listenerArgs.respond = async (response): Promise<any> => { | ||
const postResponse = await this.axios.post(body.response_url, 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.
Related to above, respond
does await
here. This means respond
may return a failure while the current say
doesn't. Also, should we be consistent about when to apply App's global error handler?
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.
Awesome catch, yes, I meant to remove the global handler catch from say
as well. I'll update that.
5794b8f
to
8469052
Compare
Updated, added new commit 8469052 |
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 PR looks great to me. Just in case, could you take a look at this? @aoberoi @stevengill
@aoberoi @stevengill Sorry for the bump, but it's been a while. I have the one pr stacked on this one (#375) and another branch in progress. It would be great to start getting feedback soon or merge this so I don't have to keep merging up! |
@@ -761,30 +814,6 @@ describe('App', () => { | |||
// Assert | |||
assert.equal(assertionAggregator.callCount, dummyReceiverEvents.length); | |||
}); | |||
|
|||
it('should handle failures through the App\'s global error handler', async () => { |
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 believe this is failing b/c the global handler doesn't know how to handle thrown errors (yet). I'm adding this test back in a later pr. Will link it when it's up.
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.
fakeReceiver.emit('message', { // IncomingEventType.Action (app.action) | ||
body: { | ||
type: 'block_actions', | ||
response_url: responseUrl, |
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.
nit: block_actions
type events will never have a response_url
. not a big deal since the functionality that's being tested is independent of the actual event type.
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.
Oh! didn't know, the types
lists it as a valid response. https://github.com/slackapi/bolt/blob/master/src/types/actions/block-action.ts#L220
I tend to not use response_url
s in favor of actual actions, so I'm not always sure which ones do.
Is that a bug then?
@barlock this is amazing work! i'm sorry my review took longer than i had initially hoped. you were super thorough and i appreciate that. i'm landing this now, and moving on to review the other PRs you've sent. |
Notes for producing the changelog:
|
Summary
Makes say, ack, and respond return promises. Per discussion in #353
I possibly changed a few things from the discussion above, I'll leave comments.
Requirements (place an
x
in each[ ]
)