Skip to content

Commit

Permalink
add retry times and retry delay for send image
Browse files Browse the repository at this point in the history
  • Loading branch information
hyzhak committed May 24, 2017
1 parent c18ed02 commit 39a8509
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 6 deletions.
4 changes: 2 additions & 2 deletions botstory/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ async def say(self, body, user, options):
return await self.send_text_message_to_all_interfaces(
recipient=user, text=body, options=options)

async def send_image(self, url, user):
tasks = [interface.send_image(user, url) for _, interface in self.interfaces.items()]
async def send_image(self, url, user, options=None):
tasks = [interface.send_image(user, url, options) for _, interface in self.interfaces.items()]
return [body for body in await asyncio.gather(*tasks)]

async def send_template(self, payload, user):
Expand Down
2 changes: 1 addition & 1 deletion botstory/chat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,4 @@ async def test_send_image(mock_interface):
await story.send_image('http://some.ua/image.gif',
user=talk.user)

mock_interface.send_image.assert_called_once_with(talk.user, 'http://some.ua/image.gif')
mock_interface.send_image.assert_called_once_with(talk.user, 'http://some.ua/image.gif', None)
20 changes: 19 additions & 1 deletion botstory/integrations/fb/messenger.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import aiohttp
import asyncio
from botstory.ast import story_context
import functools
Expand Down Expand Up @@ -162,7 +163,24 @@ async def send_list(self, recipient, elements, buttons=None, options=None):
'buttons': buttons,
})

async def send_image(self, recipient, url):
async def send_image(self, recipient, url, options=None):
if options is None:
options = {}

should_try = True
delay = options.get('retry_delay', 1)
tries = options.get('retry_times', 3)

while tries > 0 and should_try:
try:
tries -= 1
await self._send_image(recipient, url)
should_try = False
except aiohttp.http_exceptions.HttpBadRequest:
should_try = True
await asyncio.sleep(delay)

async def _send_image(self, recipient, url):
return await self.http.post(
self.api_uri + '/me/messages/',
params={
Expand Down
54 changes: 54 additions & 0 deletions botstory/integrations/fb/messenger_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,60 @@ async def test_send_image():
)


def should_post_attachment(mock_http, talk):
mock_http.post.assert_called_with(
'https://graph.facebook.com/v2.6/me/messages/',
params={
'access_token': 'qwerty1',
},
json={
'message': {
'attachment': {
'type': 'image',
'payload': {
'url': 'http://shevchenko.ua/image.gif',
},
}
},
'recipient': {
'id': talk.user['facebook_user_id'],
},
}
)


@pytest.mark.asyncio
async def test_retry_send_image():
with answer.Talk() as talk:
story = talk.story
fb_interface = story.use(messenger.FBInterface(page_access_token='qwerty1'))
mock_http = story.use(mockhttp.MockHttpInterface(
post_raise=aiohttp.http_exceptions.HttpBadRequest('fail'),
))
await story.start()

send_task = fb_interface.send_image(talk.user, 'http://shevchenko.ua/image.gif', options={
'retry_times': 3,
'retry_delay': 1,
})

async def lazy_fix_http():
# here should pass first 2 retry
await asyncio.sleep(1.5)
# than we change mock http without post raise
# so on 3 try it should pass without problem
story.use(mockhttp.MockHttpInterface())

await asyncio.gather(
lazy_fix_http(),
send_task,
)

should_post_attachment(mock_http, talk)
should_post_attachment(mock_http, talk)
should_post_attachment(mock_http, talk)


@pytest.mark.asyncio
async def test_integration():
user = utils.build_fake_user()
Expand Down
4 changes: 2 additions & 2 deletions botstory/story.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ async def ask(self, body, quick_replies=None, options=None, user=None):
async def list_elements(self, elements=None, buttons=None, user=None, options=None):
return await self.chat.list_elements(elements, buttons, user, options)

async def send_image(self, url, user):
return await self.chat.send_image(url, user)
async def send_image(self, url, user, options=None):
return await self.chat.send_image(url, user, options)

async def send_template(self, payload, user):
"""
Expand Down

0 comments on commit 39a8509

Please sign in to comment.