Мы используем Micronaut с Mongo для предоставления данных через некоторые контроллеры. Поскольку размер объектов ответа растет, нашим приложениям иногда не хватает памяти. Поэтому мы исследуем переход на драйвер async mongo и использование реактивных ответов для потоковой передачи данных клиентам. К сожалению, мы не можем изменить ни структуры ответов API, ни типы контента (все application/json
)
Один из наших API вернул сущности со следующей структурой:
[
{ "field": "value" },
{ "field": "value" },
...
{ "field": "value" }
]
Мы работали с этим контроллером, где dataStore
возвращает Publisher<Example>
:
@Get("all")
Flowable<Example> getAllExamples() {
return Flowable.fromPublisher(dataStore.find()).map(SomeMapper::toPublic);
}
Это прекрасно работает, огромный список примеров не нужно полностью загружать в память перед потоковой передачей его клиенту.
Другие API возвращают (я думаю, более разумную) структуру:
{
"list": [
{ "field": "value" },
{ "field": "value" },
...
{ "field": "value" }
],
"meta": {
...
}
}
Можем ли мы применить аналогичный шаблон «издатель / текучий» для таких сущностей, или мы застряли при загрузке данных для таких ответов в память перед их отправкой?
Мы пробовали подписи вроде:
@Get("all/dev")
Single<ExamplesWrapper> getAllDev() {
Publisher<Example> dev = dataStore.find();
return Flowable.fromPublisher(dev)
.map(mapper::map)
.collect((Callable<ArrayList<Example>>) ArrayList::new, ArrayList::add)
.map(ExampleWrapper::new);
}
Где оболочка добавляла бы некоторые метаданные. Но это снова загружает все это в память перед отправкой, что приводит к сбою приложения.
Добавление Flowable в оболочку ответа:
public class ExamplesWrapper {
private final Flowable<Example> examples;
@ConstructorProperties({"examples"})
public ExamplesWrapper(Flowable<Example> examples) {
this.examples = examples;
}
public Flowable<Example> getExamples() {
return examples;
}
}
Также не работает с некоторым приятным исключением сопоставления Джексона.
Метаданные не зависят от фактических данных примера (они добавляют некоторую статическую информацию о компании). Можем ли мы каким-то образом реализовать такую конечную точку без необходимости загружать все данные в память?