optimize song usage
This commit is contained in:
@@ -30,7 +30,7 @@ export class DbCollection<T> {
|
||||
) {}
|
||||
|
||||
public add(data: Partial<T>): Promise<DocumentReference<T>> {
|
||||
return addDoc(this.ref as CollectionReference<T>, data as WithFieldValue<T>);
|
||||
return runInInjectionContext(this.environmentInjector, () => addDoc(this.ref as CollectionReference<T>, data as WithFieldValue<T>));
|
||||
}
|
||||
|
||||
public valueChanges(options?: {idField?: string}): Observable<T[]> {
|
||||
@@ -38,7 +38,7 @@ export class DbCollection<T> {
|
||||
}
|
||||
|
||||
private get ref(): CollectionReference<DocumentData> {
|
||||
return collection(this.fs, this.path);
|
||||
return runInInjectionContext(this.environmentInjector, () => collection(this.fs, this.path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,15 +50,15 @@ export class DbDocument<T> {
|
||||
) {}
|
||||
|
||||
public set(data: Partial<T>): Promise<void> {
|
||||
return setDoc(this.ref as DocumentReference<T>, data as WithFieldValue<T>);
|
||||
return runInInjectionContext(this.environmentInjector, () => setDoc(this.ref as DocumentReference<T>, data as WithFieldValue<T>));
|
||||
}
|
||||
|
||||
public update(data: Partial<T>): Promise<void> {
|
||||
return updateDoc(this.ref, data as Partial<DocumentData>);
|
||||
return runInInjectionContext(this.environmentInjector, () => updateDoc(this.ref, data as Partial<DocumentData>));
|
||||
}
|
||||
|
||||
public delete(): Promise<void> {
|
||||
return deleteDoc(this.ref);
|
||||
return runInInjectionContext(this.environmentInjector, () => deleteDoc(this.ref));
|
||||
}
|
||||
|
||||
public collection<U>(subPath: string): DbCollection<U> {
|
||||
@@ -73,7 +73,7 @@ export class DbDocument<T> {
|
||||
}
|
||||
|
||||
private get ref(): DocumentReference<DocumentData> {
|
||||
return doc(this.fs, this.path);
|
||||
return runInInjectionContext(this.environmentInjector, () => doc(this.fs, this.path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,9 @@ export class DbService {
|
||||
return this.col(ref).valueChanges({idField: 'id'});
|
||||
}
|
||||
|
||||
const q = query(collection(this.fs, ref), ...queryConstraints);
|
||||
return runInInjectionContext(this.environmentInjector, () => collectionData(q, {idField: 'id'}) as Observable<T[]>);
|
||||
return runInInjectionContext(this.environmentInjector, () => {
|
||||
const q = query(collection(this.fs, ref), ...queryConstraints);
|
||||
return collectionData(q, {idField: 'id'}) as Observable<T[]>;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ describe('UserSongUsageService', () => {
|
||||
sessionSpy.update$.and.resolveTo();
|
||||
showDataServiceSpy.listRaw$.and.returnValue(
|
||||
of([
|
||||
{id: 'show-1', owner: 'user-1'},
|
||||
{id: 'show-2', owner: 'user-2'},
|
||||
{id: 'show-1', owner: 'user-1', archived: false},
|
||||
{id: 'show-2', owner: 'user-2', archived: true},
|
||||
] as never)
|
||||
);
|
||||
showSongDataServiceSpy.list$.and.callFake((showId: string) =>
|
||||
@@ -66,11 +66,11 @@ describe('UserSongUsageService', () => {
|
||||
await expectAsync(service.rebuildSongUsage()).toBeResolvedTo({
|
||||
usersProcessed: 2,
|
||||
showsProcessed: 2,
|
||||
showSongsProcessed: 4,
|
||||
showSongsProcessed: 3,
|
||||
});
|
||||
|
||||
expect(sessionSpy.update$).toHaveBeenCalledWith('user-1', {songUsage: {'song-1': 2, 'song-2': 1}});
|
||||
expect(sessionSpy.update$).toHaveBeenCalledWith('user-2', {songUsage: {'song-3': 1}});
|
||||
expect(sessionSpy.update$).toHaveBeenCalledWith('user-2', {songUsage: {}});
|
||||
});
|
||||
|
||||
it('should reject song usage rebuilds for non-admin users', async () => {
|
||||
|
||||
@@ -40,6 +40,10 @@ export class UserSongUsageService {
|
||||
|
||||
let showSongsProcessed = 0;
|
||||
for (const show of shows) {
|
||||
if (show.archived) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const ownerId = show.owner;
|
||||
if (!ownerId) {
|
||||
continue;
|
||||
|
||||
@@ -3,11 +3,13 @@ import {of} from 'rxjs';
|
||||
import {UserService} from './user.service';
|
||||
import {UserSessionService} from './user-session.service';
|
||||
import {UserSongUsageService} from './user-song-usage.service';
|
||||
import {ShowSongIndexService} from '../../modules/shows/services/show-song-index.service';
|
||||
|
||||
describe('UserService', () => {
|
||||
let service: UserService;
|
||||
let sessionSpy: jasmine.SpyObj<UserSessionService>;
|
||||
let songUsageSpy: jasmine.SpyObj<UserSongUsageService>;
|
||||
let showSongIndexSpy: jasmine.SpyObj<ShowSongIndexService>;
|
||||
|
||||
beforeEach(async () => {
|
||||
sessionSpy = jasmine.createSpyObj<UserSessionService>(
|
||||
@@ -20,6 +22,7 @@ describe('UserService', () => {
|
||||
}
|
||||
);
|
||||
songUsageSpy = jasmine.createSpyObj<UserSongUsageService>('UserSongUsageService', ['incSongCount', 'decSongCount', 'rebuildSongUsage']);
|
||||
showSongIndexSpy = jasmine.createSpyObj<ShowSongIndexService>('ShowSongIndexService', ['rebuildShowSongIds']);
|
||||
|
||||
sessionSpy.currentUser.and.resolveTo({id: 'user-1'} as never);
|
||||
sessionSpy.getUserbyId.and.resolveTo({id: 'user-2'} as never);
|
||||
@@ -34,11 +37,13 @@ describe('UserService', () => {
|
||||
songUsageSpy.incSongCount.and.resolveTo();
|
||||
songUsageSpy.decSongCount.and.resolveTo();
|
||||
songUsageSpy.rebuildSongUsage.and.resolveTo({usersProcessed: 1, showsProcessed: 2, showSongsProcessed: 3});
|
||||
showSongIndexSpy.rebuildShowSongIds.and.resolveTo({showsProcessed: 2, showSongsProcessed: 3});
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: UserSessionService, useValue: sessionSpy},
|
||||
{provide: UserSongUsageService, useValue: songUsageSpy},
|
||||
{provide: ShowSongIndexService, useValue: showSongIndexSpy},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -100,9 +105,11 @@ describe('UserService', () => {
|
||||
await service.incSongCount('song-1');
|
||||
await service.decSongCount('song-2');
|
||||
await expectAsync(service.rebuildSongUsage()).toBeResolvedTo({usersProcessed: 1, showsProcessed: 2, showSongsProcessed: 3});
|
||||
await expectAsync(service.rebuildShowSongIds()).toBeResolvedTo({showsProcessed: 2, showSongsProcessed: 3});
|
||||
|
||||
expect(songUsageSpy.incSongCount).toHaveBeenCalledWith('song-1');
|
||||
expect(songUsageSpy.decSongCount).toHaveBeenCalledWith('song-2');
|
||||
expect(songUsageSpy.rebuildSongUsage).toHaveBeenCalled();
|
||||
expect(showSongIndexSpy.rebuildShowSongIds).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import {Observable} from 'rxjs';
|
||||
import {User} from './user';
|
||||
import {SongUsageMigrationResult, UserSongUsageService} from './user-song-usage.service';
|
||||
import {UserSessionService} from './user-session.service';
|
||||
import {MigrationProgress, ShowSongIndexMigrationResult, ShowSongIndexService} from '../../modules/shows/services/show-song-index.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -10,6 +11,7 @@ import {UserSessionService} from './user-session.service';
|
||||
export class UserService {
|
||||
private session = inject(UserSessionService);
|
||||
private songUsage = inject(UserSongUsageService);
|
||||
private showSongIndex = inject(ShowSongIndexService);
|
||||
|
||||
public users$ = this.session.users$;
|
||||
|
||||
@@ -34,4 +36,6 @@ export class UserService {
|
||||
public incSongCount = (songId: string): Promise<void | null> => this.songUsage.incSongCount(songId);
|
||||
public decSongCount = (songId: string): Promise<void | null> => this.songUsage.decSongCount(songId);
|
||||
public rebuildSongUsage = (): Promise<SongUsageMigrationResult> => this.songUsage.rebuildSongUsage();
|
||||
public rebuildShowSongIds = (onProgress?: (progress: MigrationProgress) => void): Promise<ShowSongIndexMigrationResult> =>
|
||||
this.showSongIndex.rebuildShowSongIds(onProgress);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user