feat: streaming entities
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import { ref, computed, readonly } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { entityService } from '../services'
|
||||
import { EntityObject } from '../models'
|
||||
import type { EntityTransmitRequest, EntityTransmitResponse } from '../types/entity'
|
||||
import type { EntityTransmitRequest, EntityTransmitResponse, EntityStreamRequest } from '../types/entity'
|
||||
import type { SourceSelector, ListFilter, ListSort, ListRange } from '../types/common'
|
||||
|
||||
export const useEntitiesStore = defineStore('mailEntitiesStore', () => {
|
||||
@@ -103,26 +103,16 @@ export const useEntitiesStore = defineStore('mailEntitiesStore', () => {
|
||||
async function list(sources?: SourceSelector, filter?: ListFilter, sort?: ListSort, range?: ListRange): Promise<Record<string, EntityObject>> {
|
||||
transceiving.value = true
|
||||
try {
|
||||
const response = await entityService.list({ sources, filter, sort, range })
|
||||
const added: Record<string, EntityObject> = {}
|
||||
|
||||
// Flatten nested structure: provider:service:collection:entity -> "provider:service:collection:entity": object
|
||||
const entities: Record<string, EntityObject> = {}
|
||||
Object.entries(response).forEach(([providerId, providerServices]) => {
|
||||
Object.entries(providerServices).forEach(([serviceId, serviceCollections]) => {
|
||||
Object.entries(serviceCollections).forEach(([collectionId, collectionEntities]) => {
|
||||
Object.entries(collectionEntities).forEach(([entityId, entityData]) => {
|
||||
const key = identifierKey(providerId, serviceId, collectionId, entityId)
|
||||
entities[key] = entityData
|
||||
})
|
||||
})
|
||||
})
|
||||
await entityService.stream({ sources, filter, sort, range }, (entity: EntityObject) => {
|
||||
const key = identifierKey(entity.provider, entity.service, entity.collection, entity.identifier)
|
||||
_entities.value[key] = entity
|
||||
added[key] = entity
|
||||
})
|
||||
|
||||
// Merge retrieved entities into state
|
||||
_entities.value = { ..._entities.value, ...entities }
|
||||
|
||||
console.debug('[Mail Manager][Store] - Successfully retrieved', Object.keys(entities).length, 'entities')
|
||||
return entities
|
||||
console.debug('[Mail Manager][Store] - Successfully retrieved', Object.keys(added).length, 'entities')
|
||||
return added
|
||||
} catch (error: any) {
|
||||
console.error('[Mail Manager][Store] - Failed to retrieve entities:', error)
|
||||
throw error
|
||||
@@ -346,6 +336,42 @@ export const useEntitiesStore = defineStore('mailEntitiesStore', () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream entities progressively, merging each entity into the store as it arrives.
|
||||
*
|
||||
* Unlike list(), which waits for the full response before updating the store,
|
||||
* stream() updates reactive state entity-by-entity so UI renders incrementally.
|
||||
*
|
||||
* @param sources - optional source selector
|
||||
* @param filter - optional list filter
|
||||
* @param sort - optional list sort
|
||||
* @param range - optional list range
|
||||
*
|
||||
* @returns Promise resolving to { total } when the stream completes
|
||||
*/
|
||||
async function stream(
|
||||
sources?: SourceSelector,
|
||||
filter?: ListFilter,
|
||||
sort?: ListSort,
|
||||
range?: ListRange
|
||||
): Promise<{ total: number }> {
|
||||
transceiving.value = true
|
||||
try {
|
||||
const request: EntityStreamRequest = { sources, filter, sort, range }
|
||||
const result = await entityService.stream(request, (entity: EntityObject) => {
|
||||
const key = identifierKey(entity.provider, entity.service, entity.collection, entity.identifier)
|
||||
_entities.value[key] = entity
|
||||
})
|
||||
console.debug('[Mail Manager][Store] - Successfully streamed', result.total, 'entities')
|
||||
return result
|
||||
} catch (error: any) {
|
||||
console.error('[Mail Manager][Store] - Failed to stream entities:', error)
|
||||
throw error
|
||||
} finally {
|
||||
transceiving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Return public API
|
||||
return {
|
||||
// State (readonly)
|
||||
@@ -365,5 +391,6 @@ export const useEntitiesStore = defineStore('mailEntitiesStore', () => {
|
||||
delete: remove,
|
||||
delta,
|
||||
transmit,
|
||||
stream,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user