Одна из моих веб-страниц занимает около 3 секунд для локальной загрузки и 15 секунд для загрузки в режиме реального времени на Heroku. Я считаю, что проблема заключается в том, сколько синхронных вызовов API Google TTS (Text-To-Speech) и синхронной базы данных / записей Amazon S3 я выполняю.
Я думаю, что асинхронное кодирование поможет, но я не совсем уверен, как его реализовать. Вот что происходит в представлении:
# views.py
def convert_str_to_audio_info_if_necessary(audio_str):
audio_info = AudioInfo.objects.get_by_text(audio_str)
if audio_info is None:
audio_content = synthesize_text(audio_str) # returns audio file from Google
# WAIT for the response to come back from Google's API
new_audio = ContentFile(audio_content, 'audio.wav') # converts to file Python can read
audio_info = AudioInfo.objects.create_problem_audio(text=audio_str, audio=new_audio, duration=get_audio_file_duration(new_audio))
# WAIT for the audio file to be written to my S3 bucket
return audio_info
def slow_loading_view(request):
for i in range(100):
audio_str = str(i)
audio_info = convert_str_to_audio_info_if_necessary(audio_str)
context[audio_str] = audio_info
# Now I would like to pass this data in my context to use in the webpage
return render(request, 'my_page.html', context)
И мой в моей модели:
# models.py
class AudioInfoManager(models.Manager):
def get_by_text(self, text):
qs = self.get_queryset().filter(text=text)
if len(qs) == 0:
return None
return qs[0]
def create_problem_audio(self, text, audio, duration):
already_created_entry = self.get_by_text(text)
if already_created_entry != None:
return already_created_entry
problem_audio = self.create(text=text, audio=audio, duration=duration)
return problem_audio
class AudioInfo(models.Model):
text = models.TextField(unique=True)
audio = models.FileField(upload_to=upload_audio_info_path)
duration = models.FloatField()
objects = AudioInfoManager()
Как вы можете видеть, в представлении происходит большое время ожидания (простоя), поэтому в идеале я бы смог 1) асинхронно отправлять все запросы API Google для создания аудиофайлов, а затем после того, как я вернуть все эти аудиофайлы 2) асинхронно записать эти аудиофайлы в базу данных и сегменты S3, а затем, как только они все будут записаны, 3) запросить в базе данных свои данные и передать данные в качестве контекста для отображения моей веб-страницы.
Кажется, что все асинхронные библиотеки в Django, такие как Celery и Redis Queue, помогают только в фоновых задачах (задачах, которые не требуется выполнять перед отображением веб-страницы представления, например, отправка электронных писем, запись данных в базу данных, которая не на веб-странице и т. д.). Возможно, каналы asyncio или Django - это решения? Django - это синхронный фреймворк, поэтому я не уверен, могу ли я обновлять базу данных асинхронно.
Есть предложения, что мне делать?