Skip to content

Commit

Permalink
Implement memory cache for PostCaptures (#600)
Browse files Browse the repository at this point in the history
* Implement memory cache for PostCaptures.

* Deduplicate value emission from postCaptures$.
  • Loading branch information
seanwu1105 authored Mar 30, 2021
1 parent 791dc92 commit f70fe75
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@

<mat-list *ngIf="diaBackendAsset$ | async as diaBackendAsset">
<ion-img
[routerLink]="['/image-viewer', diaBackendAsset.asset_file]"
[src]="diaBackendAsset.asset_file"
*ngIf="imageSrc$ | async as imageSrc"
[routerLink]="['/image-viewer', imageSrc]"
[src]="imageSrc"
></ion-img>
<mat-list-item>
<mat-icon mat-list-icon>person</mat-icon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ActionSheetController } from '@ionic/angular';
import { TranslocoService } from '@ngneat/transloco';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { zip } from 'rxjs';
import { map, shareReplay, switchMap } from 'rxjs/operators';
import { first, map, shareReplay, switchMap } from 'rxjs/operators';
import {
DiaBackendAsset,
DiaBackendAssetRepository,
Expand All @@ -27,7 +27,16 @@ export class PostCaptureDetailsPage {
readonly diaBackendAsset$ = this.route.paramMap.pipe(
map(params => params.get('id')),
isNonNullable(),
switchMap(id => this.diaBackendAssetRepository.fetchById$(id)),
switchMap(id => this.diaBackendAssetRepository.getPostCaptureById$(id)),
shareReplay({ bufferSize: 1, refCount: true })
);

readonly imageSrc$ = this.diaBackendAsset$.pipe(
switchMap(asset =>
this.diaBackendAssetRepository.getAndCachePostCaptureImage$(asset)
),
first(),
map(blob => URL.createObjectURL(blob)),
shareReplay({ bufferSize: 1, refCount: true })
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class PostCaptureTabComponent {
switchMap(isConnected =>
iif(
() => isConnected,
this.diaBackendAssetRepository.getPostCaptures$().pipe(
this.diaBackendAssetRepository.postCaptures$.pipe(
pluck('results'),
map(assets => assets.filter(a => a.source_transaction))
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,31 @@ import {
HttpParams,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { defer, forkJoin, iif, of, Subject, throwError } from 'rxjs';
import {
BehaviorSubject,
defer,
forkJoin,
iif,
merge,
of,
ReplaySubject,
Subject,
throwError,
} from 'rxjs';
import {
catchError,
concatMap,
distinctUntilChanged,
first,
map,
pluck,
repeatWhen,
switchMap,
tap,
} from 'rxjs/operators';
import { base64ToBlob } from '../../../../utils/encoding/encoding';
import { toExtension } from '../../../../utils/mime-type';
import { isNonNullable } from '../../../../utils/rx-operators/rx-operators';
import { Tuple } from '../../database/table/table';
import {
getOldProof,
Expand All @@ -33,6 +48,14 @@ import { BASE_URL } from '../secret';
providedIn: 'root',
})
export class DiaBackendAssetRepository {
private readonly postCapturesCache$ = new ReplaySubject<
PaginatedResponse<DiaBackendAsset>
>(1);

private readonly postCapturesImageCache$ = new BehaviorSubject(
new Map<string, Blob>()
);

readonly fetchCapturesCount$ = this.list$({
limit: 1,
isOriginalOwner: true,
Expand All @@ -48,6 +71,24 @@ export class DiaBackendAssetRepository {

private readonly postCapturesUpdated$ = new Subject<{ reason?: string }>();

readonly postCaptures$ = merge(
this.postCapturesCache$,
this.postCapturesCount$.pipe(
first(),
concatMap(count =>
this.list$({
isOriginalOwner: false,
orderBy: 'source_transaction',
limit: count,
})
),
tap(response => this.postCapturesCache$.next(response))
)
).pipe(
distinctUntilChanged(),
repeatWhen(() => this.postCapturesUpdated$)
);

constructor(
private readonly httpClient: HttpClient,
private readonly authService: DiaBackendAuthService
Expand All @@ -73,26 +114,34 @@ export class DiaBackendAssetRepository {
return this.list$({ offset, limit, isOriginalOwner: true });
}

getPostCaptures$(options?: { limit?: number; offset?: number }) {
return iif(
() => options?.limit !== undefined,
this.list$({
isOriginalOwner: false,
orderBy: 'source_transaction',
limit: options?.limit,
offset: options?.offset,
}),
this.postCapturesCount$.pipe(
first(),
concatMap(count =>
this.list$({
isOriginalOwner: false,
orderBy: 'source_transaction',
limit: count,
})
getPostCaptureById$(id: string) {
return merge(
this.postCapturesCache$.pipe(
map(postCaptures => postCaptures.results.find(p => p.id === id)),
isNonNullable()
),
this.fetchById$(id)
);
}

getAndCachePostCaptureImage$(postCapture: DiaBackendAsset) {
return this.postCapturesImageCache$.pipe(
map(cache => cache.get(postCapture.id)),
switchMap(image =>
iif(
() => !!image,
of(image).pipe(isNonNullable()),
this.downloadFile$({ id: postCapture.id, field: 'asset_file' }).pipe(
first(),
tap(blob => {
const currentCache = this.postCapturesImageCache$.value;
currentCache.set(postCapture.id, blob);
this.postCapturesImageCache$.next(currentCache);
})
)
)
)
).pipe(repeatWhen(() => this.postCapturesUpdated$));
);
}

private list$({
Expand Down
3 changes: 1 addition & 2 deletions src/app/shared/services/migration/migration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ export class MigrationService {
}

private async fetchAllPostCaptures() {
return this.diaBackendAssetRepository
.getPostCaptures$()
return this.diaBackendAssetRepository.postCaptures$
.pipe(first(), pluck('results'))
.toPromise();
}
Expand Down

0 comments on commit f70fe75

Please sign in to comment.