надо, что-то типа бэкграунд Thread, но на корутина...
# russian
a
надо, что-то типа бэкграунд Thread, но на корутинах
g
Корутины уже могут работать как бэкграунд тред
Непонятна суть проблему, почему при загрузке нескольких файлов у вас появляются битые файлы
a
Приложение на spring и я погуглил, вроде как высвобождаются ресурсы после ответа от контроллера, поэтому файлы могу не дозаписываться. Но мне кажется в другом проблема все таки. Если загружать один файл размером 300mb, то все ок он запишется спустя какое-то время, а если за ним сразу загрузить второй, то не запишутся оба... Для загрузки файла использую, что-то типа launch { Files().write(path, bytes) }.start
g
Зачем нужен start? Launch и так по умолчанию стартует и этот код выполнится в бэкграунде
a
можно и убрать, но проблемы это не решит)
Я думаю, что происходит примерно следующее: файл передается в launch и не успевает записаться т.к это всего лишь ссылка на MultipartFile, пока считывается ByteArray туда прилетает уже следующий запрос с другим файлом и перезаписывает предыдущий, ресурсы высвобождаются и короче трындец наступает.
просто как версия
g
Я не знаю как спринг менеджерит такие ресурсы, т.е. вы записываете файл от юзера полученный в реквесте? Если так, то конечно возвращать результат нельзя, пока файл не скачан и не закеширован на диск, иначе просто запрос прервется
a
Андрей, все верно)
g
ну тогда нужно для начала дождаться получение всего запроса, закешировать файл, и только после этого отвечать то что вы хотите, т.е. можно сэкономить только на времени процессинга данных юзера, но нельзя ответить пок все данные не получены. Если есть какой то процессинг, то launch вполне подойдет как просто замена бэкграунд треду, можно конечно сделать более продакшн реди решение, и слать закешированые файлы в канал, а из него будут воркеры брать данные и процесить, это что бы решить проблема слишком большого числа процессоров
a
Я вчера начал в эту же сторону копать, но все равно не до конца понимаю. Если нам от юзера прилетает файл и дальше мы его закинем в channel, то все равно, если сразу после этого прилетит второй файл от того же юзера у нас ссылка переопределиться и мы будем в другое место памяти смотреть. Поправьте если неправ
g
Для начала нужно понять что такое “от юзера прилетает файл”
это файл уже записаный на диск из юзерского запроса?
если сразу после этого прилетит второй файл от того же юзера у нас ссылка переопределиться и мы будем в другое место памяти смотреть
тут в любом случае каждый файл нужно пписать с уникальным именем, тут корутины и каналы не причем
ну т.е. или каждый файл по своему пути, или просто не обрабатывать новые запросы, ппока предыдущие не обработаны, но наврядли такой вариант имеет смысл, так как будет пользовательские запросы задерживать Поэтому просто все полученые файлы ппо уникальному имени, потом передаете в канал, из которого воркеры их берут, процесят и удаляют к примеру времененные файлы
a
Смотрите, пользователь делает upload со своей локальной машины, далее файл из контроллера я передаю в процессинговую часть, там очень быстро разбирается мета инфа файла и ему присваивается уникальное имя, запись мета информации в БД происходит до записи файла на диск, то есть в принципе ничего не мешает вернуть ответ юзеру с сылкой на загруженный файл, а файл потихоньку загрузить в фоне. Но, если этот же самый юзер в рамках своей сессии, сразу закинет еще один файл, то я не очень понимаю как дописать предыдущий файл т.к новый файл переопределит ссылку записываемого файла в heap jvm... Если только каждый раз делать копию объекта и пихать его в worker.
g
ничего не мешает вернуть ответ юзеру с сылкой на загруженный файл, а файл потихоньку загрузить в фоне
Не представляю как это может работать в рамках HTTP запросов. В HTTP ответ всегда следует за запросом, не возможно прочитав часть запроса, сделать ответ и потом вернуться к получению запроса
и тут дело не во множественных запросах, а просто в том как http работает
a
ну скажем, если сразу второй файл не отправлять, то все работает нормально. Я генерирую мета инфу и отдаю ее, а файл становится доступен только после загрузки
в любом случае это неправильно, тут Вы правы
g
что-то я очень в этом сомневаюсь, видимо просто ответ не уходит пока вы его читаете или еще нечто подобное
нужно сперва полностью получить файл, паралельно, даже не дожидаясь записи всего файла на диск/память можно сгенерить мета данне, записать их в базу, как только мета данные будут готовы и сам файл будут кеширован, вы можете вернуть юзеру ответ и отправить данные в процессор, тоже паралельно
но возвращать ответ, не дождавшись загрузки запроса точно не правильно
Может быть какие то более хитрые вещи, вроде мультиплексирования через HTTP/2 позволят такое сделать (вернуть ответ, паралельно читая запрос), но мне кажется клиент тоже должен такое поддерживать и все равно не уверен что это татк просто, а главное зачем клиенту знать эту самую мету, пока файл еще даже не загружен, потому что если загрузка оборвется, то файл надо будет загружать повторно, или даже с поддержкой докачки и не понятно что там будет с этой метаинформацией, которую вы уже венули
l
можно вернуть из контроллера Mono/CompletableFeature и разрешить их по факту завершения launch{} таска