From d882b22f2e870fa152f72b85cfd520bc16fcd34a Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 9 Aug 2020 22:04:54 +0800 Subject: Merge sync status into subscription hub. --- Timeline/ClientApp/src/app/data/user.ts | 127 +++++++++++++------------------- 1 file changed, 53 insertions(+), 74 deletions(-) (limited to 'Timeline/ClientApp/src/app/data/user.ts') diff --git a/Timeline/ClientApp/src/app/data/user.ts b/Timeline/ClientApp/src/app/data/user.ts index 5b96e2b6..d19a6323 100644 --- a/Timeline/ClientApp/src/app/data/user.ts +++ b/Timeline/ClientApp/src/app/data/user.ts @@ -6,8 +6,7 @@ import { UiLogicError } from '../common'; import { convertError } from '../utilities/rxjs'; import { pushAlert } from '../common/alert-service'; -import { dataStorage } from './common'; -import { syncStatusHub } from './SyncStatusHub'; +import { dataStorage, throwIfNotNetworkError } from './common'; import { SubscriptionHub } from './SubscriptionHub'; import { HttpNetworkError, BlobWithEtag, NotModified } from '../http/common'; @@ -229,47 +228,45 @@ export class UserNotExistError extends Error {} export class UserInfoService { async saveUser(user: HttpUser): Promise { - const syncStatusKey = `user.${user.username}`; - if (syncStatusHub.get(syncStatusKey)) return; - syncStatusHub.begin(syncStatusKey); + const key = user.username; + const line = this._userHub.getLineOrCreateWithoutSetup(key); + if (line.isSyncing) return; + line.beginSync(); await this.doSaveUser(user); - syncStatusHub.end(syncStatusKey); - this._userHub.getLine(user.username)?.next({ user, type: 'synced' }); + line.endSyncAndNext({ user, type: 'synced' }); } private getCachedUser(username: string): Promise { return dataStorage.getItem(`user.${username}`); } - private async doSaveUser(user: HttpUser): Promise { - await dataStorage.setItem(`user.${user.username}`, user); + private doSaveUser(user: HttpUser): Promise { + return dataStorage.setItem(`user.${user.username}`, user).then(); } private async syncUser(username: string): Promise { - const syncStatusKey = `user.${username}`; - if (syncStatusHub.get(syncStatusKey)) return; - syncStatusHub.begin(syncStatusKey); + const line = this._userHub.getLineOrCreateWithoutSetup(username); + if (line.isSyncing) return; + line.beginSync(); + + if (line.value == undefined) { + const cache = await this.getCachedUser(username); + if (cache != null) { + line.next({ user: cache, type: 'cache' }); + } + } try { const res = await getHttpUserClient().get(username); await this.doSaveUser(res); - syncStatusHub.end(syncStatusKey); - this._userHub.getLine(username)?.next({ user: res, type: 'synced' }); + line.endSyncAndNext({ user: res, type: 'synced' }); } catch (e) { if (e instanceof HttpUserNotExistError) { - syncStatusHub.end(syncStatusKey); - this._userHub.getLine(username)?.next({ type: 'notexist' }); + line.endSyncAndNext({ type: 'notexist' }); } else { - syncStatusHub.end(syncStatusKey); - const line = this._userHub.getLine(username); - if (line != null) { - const cache = await this.getCachedUser(username); - if (cache == null) line.next({ type: 'offline' }); - else line.next({ user: cache, type: 'offline' }); - } - if (!(e instanceof HttpNetworkError)) { - throw e; - } + const cache = await this.getCachedUser(username); + line.endSyncAndNext({ user: cache ?? undefined, type: 'offline' }); + throwIfNotNetworkError(e); } } } @@ -279,13 +276,8 @@ export class UserInfoService { | { user: User; type: 'cache' | 'synced' | 'offline' } | { user?: undefined; type: 'notexist' | 'offline' } >({ - setup: (key, line) => { - void this.getCachedUser(key).then((cache) => { - if (cache != null) { - line.next({ user: cache, type: 'cache' }); - } - return this.syncUser(key); - }); + setup: (key) => { + void this.syncUser(key); }, }); @@ -296,58 +288,50 @@ export class UserInfoService { ); } - private getCachedAvatar(username: string): Promise { + private getCachedAvatar(username: string): Promise { + return dataStorage.getItem(`user.${username}.avatar`); + } + + private saveAvatar(username: string, data: BlobWithEtag): Promise { return dataStorage - .getItem(`user.${username}.avatar`) - .then((data) => data?.data ?? null); + .setItem(`user.${username}.avatar`, data) + .then(); } private async syncAvatar(username: string): Promise { - const syncStatusKey = `user.avatar.${username}`; - if (syncStatusHub.get(syncStatusKey)) return; - syncStatusHub.begin(syncStatusKey); + const line = this._avatarHub.getLineOrCreateWithoutSetup(username); + if (line.isSyncing) return; + line.beginSync(); + + const cache = await this.getCachedAvatar(username); + if (line.value == null) { + if (cache != null) { + line.next({ data: cache.data, type: 'cache' }); + } + } - const dataKey = `user.${username}.avatar`; - const cache = await dataStorage.getItem(dataKey); if (cache == null) { try { const avatar = await getHttpUserClient().getAvatar(username); - await dataStorage.setItem(dataKey, avatar); - syncStatusHub.end(syncStatusKey); - this._avatarHub - .getLine(username) - ?.next({ data: avatar.data, type: 'synced' }); + await this.saveAvatar(username, avatar); + line.endSyncAndNext({ data: avatar.data, type: 'synced' }); } catch (e) { - syncStatusHub.end(syncStatusKey); - this._avatarHub.getLine(username)?.next({ type: 'offline' }); - if (!(e instanceof HttpNetworkError)) { - throw e; - } + line.endSyncAndNext({ type: 'offline' }); + throwIfNotNetworkError(e); } } else { try { const res = await getHttpUserClient().getAvatar(username, cache.etag); if (res instanceof NotModified) { - syncStatusHub.end(syncStatusKey); - this._avatarHub - .getLine(username) - ?.next({ data: cache.data, type: 'synced' }); + line.endSyncAndNext({ data: cache.data, type: 'synced' }); } else { const avatar = res; - await dataStorage.setItem(dataKey, avatar); - syncStatusHub.end(syncStatusKey); - this._avatarHub - .getLine(username) - ?.next({ data: avatar.data, type: 'synced' }); + await this.saveAvatar(username, avatar); + line.endSyncAndNext({ data: avatar.data, type: 'synced' }); } } catch (e) { - syncStatusHub.end(syncStatusKey); - this._avatarHub - .getLine(username) - ?.next({ data: cache.data, type: 'offline' }); - if (!(e instanceof HttpNetworkError)) { - throw e; - } + line.endSyncAndNext({ data: cache.data, type: 'offline' }); + throwIfNotNetworkError(e); } } } @@ -357,13 +341,8 @@ export class UserInfoService { | { data: Blob; type: 'cache' | 'synced' | 'offline' } | { data?: undefined; type: 'notexist' | 'offline' } >({ - setup: (key, line) => { - void this.getCachedAvatar(key).then((avatar) => { - if (avatar != null) { - line.next({ data: avatar, type: 'cache' }); - } - return this.syncAvatar(key); - }); + setup: (key) => { + void this.syncAvatar(key); }, }); -- cgit v1.2.3