Skip to content

Commit

Permalink
refactor: improve sqlite cache + add new methods for item-preview (#529)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancescoBorzi committed Mar 26, 2020
1 parent 201b47e commit 045db7f
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 42 deletions.
25 changes: 1 addition & 24 deletions src/app/shared/services/mysql-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { map, tap } from 'rxjs/operators';
import { Squel, Delete, Insert, Update } from 'squel';

import { MysqlService } from './mysql.service';
import { MaxRow, TableRow, ValueRow } from '../types/general';
import { MaxRow, TableRow } from '../types/general';
import { squelConfig } from '../../config/squel.config';
import { ConfigService } from './config.service';
import { QueryService } from '@keira-shared/services/query.service';
Expand All @@ -19,7 +19,6 @@ declare const squel: Squel & {flavour: null};
export class MysqlQueryService extends QueryService {

private readonly QUERY_NO_CHANGES = '-- There are no changes';
private cache: { [key: string]: Promise<string>[] } = {};

constructor(
private mysqlService: MysqlService,
Expand Down Expand Up @@ -355,28 +354,6 @@ export class MysqlQueryService extends QueryService {
);
}


// Input query format must be: SELECT something AS v FROM ...
queryValue(query: string): Observable<string> {
return this.query(query).pipe(
map((data: ValueRow[]) => data.length > 0 ? data[0].v : null),
);
}

queryValueToPromise(query: string): Promise<string> {
return this.queryValue(query).toPromise();
}

queryValueToPromiseCached(cacheId: string, id: string, query: string): Promise<string> {
if (!this.cache[cacheId]) {
this.cache[cacheId] = [];
}
if (!this.cache[cacheId][id]) {
this.cache[cacheId][id] = this.queryValue(query).toPromise();
}
return this.cache[cacheId][id];
}

getCreatureNameById(id: string|number): Promise<string> {
return this.queryValueToPromiseCached('getCreatureNameById', String(id), `SELECT name AS v FROM creature_template WHERE entry = ${id}`);
}
Expand Down
33 changes: 33 additions & 0 deletions src/app/shared/services/query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,44 @@ import * as squel from 'squel';

import { QueryForm, TableRow } from '@keira-types/general';
import { squelConfig } from '@keira-config/squel.config';
import { map } from 'rxjs/operators';

export abstract class QueryService {
protected cache: { [key: string]: Promise<string>[] } = {};

abstract query<T extends TableRow>(queryString: string): Observable<T[]>;

// Input query format must be: SELECT something AS v FROM ...
queryValue<T extends string | number>(query: string): Observable<T | null> {
return this.query(query).pipe(
map(data => data && data[0] ? data[0].v as T : null),
);
}

queryValueToPromise<T extends string | number>(query: string): Promise<T> {
return this.queryValue<T>(query).toPromise();
}

queryToPromiseCached<T extends TableRow>(cacheId: string, id: string, query: string): Promise<T[]> {
if (!this.cache[cacheId]) {
this.cache[cacheId] = [];
}
if (!this.cache[cacheId][id]) {
this.cache[cacheId][id] = this.query<T>(query).toPromise();
}
return this.cache[cacheId][id];
}

queryValueToPromiseCached<T extends string | number>(cacheId: string, id: string, query: string): Promise<T> {
if (!this.cache[cacheId]) {
this.cache[cacheId] = [];
}
if (!this.cache[cacheId][id]) {
this.cache[cacheId][id] = this.queryValue<T>(query).toPromise();
}
return this.cache[cacheId][id];
}

getSearchQuery(table: string, queryForm: QueryForm, selectFields: string[] = null, groupFields: string[] = null): string {
const query = squel.select(squelConfig).from(table);

Expand Down
75 changes: 73 additions & 2 deletions src/app/shared/services/sqlite-query.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,83 @@ describe('SqliteQueryService', () => {

it('getSpellNameById', async () => {
expect(await service.getSpellNameById(id)).toEqual(mockResult);
expect(await service.getSpellNameById(id)).toEqual(mockResult);
expect(service.queryValue).toHaveBeenCalledTimes(1);
expect(await service.getSpellNameById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT spellName AS v FROM spells WHERE id = ${id}`
);
});

it('getSkillNameById', async () => {
expect(await service.getSkillNameById(id)).toEqual(mockResult);
expect(await service.getSkillNameById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT name AS v FROM skills WHERE id = ${id}`
);
});

it('getFactionNameById', async () => {
expect(await service.getFactionNameById(id)).toEqual(mockResult);
expect(await service.getFactionNameById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT m_name_lang_1 AS v FROM factions WHERE m_ID = ${id}`
);
});

it('getMapNameById', async () => {
expect(await service.getMapNameById(id)).toEqual(mockResult);
expect(await service.getMapNameById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT m_MapName_lang1 AS v FROM maps WHERE m_ID = ${id}`
);
});

it('getAreaNameById', async () => {
expect(await service.getAreaNameById(id)).toEqual(mockResult);
expect(await service.getAreaNameById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT m_AreaName_lang AS v FROM areas_and_zones WHERE m_ID = ${id}`
);
});

it('getEventNameByHolidayId', async () => {
expect(await service.getEventNameByHolidayId(id)).toEqual(mockResult);
expect(await service.getEventNameByHolidayId(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT name AS v FROM holiday WHERE id = ${id}`
);
});

it('getSocketBonusById', async () => {
expect(await service.getSocketBonusById(id)).toEqual(mockResult);
expect(await service.getSocketBonusById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT name AS v FROM item_enchantment WHERE id = ${id}`
);
});

it('getSpellDescriptionById', async () => {
expect(await service.getSpellDescriptionById(id)).toEqual(mockResult);
expect(await service.getSpellDescriptionById(id)).toEqual(mockResult); // check cache
expect(service.queryValue).toHaveBeenCalledTimes(1); // check cache
expect(service.queryValue).toHaveBeenCalledWith(
`SELECT Description AS v FROM spells WHERE id = ${id}`
);
});

it('getLockById', async () => {
spyOn(service, 'query').and.returnValue(of([]));
expect(await service.getLockById(id)).toEqual([]);
expect(await service.getLockById(id)).toEqual([]); // check cache
expect(service.query).toHaveBeenCalledTimes(1); // check cache
expect(service.query).toHaveBeenCalledWith(`SELECT * FROM lock WHERE id = ${id}`);
});
});

});
51 changes: 35 additions & 16 deletions src/app/shared/services/sqlite-query.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map, shareReplay, tap } from 'rxjs/operators';
import { shareReplay, tap } from 'rxjs/operators';

import { SqliteService } from '@keira-shared/services/sqlite.service';
import { ConfigService } from '@keira-shared/services/config.service';
import { TableRow } from '@keira-types/general';
import { QueryService } from '@keira-shared/services/query.service';
import { Lock } from '@keira-types/lock.type';

@Injectable({
providedIn: 'root'
})
export class SqliteQueryService extends QueryService {

private itemDisplayIdCache: Observable<string>[] = [];
private spellNameCache: Promise<string>[] = [];

constructor(
private sqliteService: SqliteService,
Expand All @@ -34,13 +34,6 @@ export class SqliteQueryService extends QueryService {
);
}

// Input query format must be: SELECT something AS v FROM ...
queryValue<T extends string | number>(query: string): Observable<T | null> {
return this.query(query).pipe(
map((data) => data && data[0] ? data[0].v as T : null),
);
}

getIconByItemDisplayId(displayId: string | number): Observable<string> {
displayId = Number(displayId);

Expand All @@ -54,14 +47,40 @@ export class SqliteQueryService extends QueryService {
}

getSpellNameById(spellId: string | number): Promise<string> {
spellId = Number(spellId);
return this.queryValueToPromiseCached('getSpellNameById', String(spellId), `SELECT spellName AS v FROM spells WHERE id = ${spellId}`);
}

if (!this.spellNameCache[spellId]) {
this.spellNameCache[spellId] = this.queryValue<string>(
`SELECT spellName AS v FROM spells WHERE id = ${spellId}`
).pipe(shareReplay()).toPromise();
}
getSkillNameById(skillId: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>(
'getSkillNameById', String(skillId), `SELECT name AS v FROM skills WHERE id = ${skillId}`
);
}

getFactionNameById(id: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getFactionNameById', String(id), `SELECT m_name_lang_1 AS v FROM factions WHERE m_ID = ${id}`);
}

getMapNameById(id: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getMapNameById', String(id), `SELECT m_MapName_lang1 AS v FROM maps WHERE m_ID = ${id}`);
}

getAreaNameById(id: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getAreaNameById', String(id), `SELECT m_AreaName_lang AS v FROM areas_and_zones WHERE m_ID = ${id}`);
}

getEventNameByHolidayId(id: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getEventNameByHolidayId', String(id), `SELECT name AS v FROM holiday WHERE id = ${id}`);
}

getSocketBonusById(id: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getSocketBonusById', String(id), `SELECT name AS v FROM item_enchantment WHERE id = ${id}`);
}

getSpellDescriptionById(spellId: string | number): Promise<string> {
return this.queryValueToPromiseCached<string>('getSpellDescriptionById', String(spellId), `SELECT Description AS v FROM spells WHERE id = ${spellId}`);
}

return this.spellNameCache[spellId];
getLockById(id: string | number): Promise<Lock[]> {
return this.queryToPromiseCached<Lock>('getLockById', String(id), `SELECT * FROM lock WHERE id = ${id}`);
}
}
20 changes: 20 additions & 0 deletions src/app/shared/types/lock.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { TableRow } from '@keira-types/general';

export class Lock extends TableRow {
id: number;
type1: number;
type2: number;
type3: number;
type4: number;
type5: number;
properties1: number;
properties2: number;
properties3: number;
properties4: number;
properties5: number;
reqSkill1: number;
reqSkill2: number;
reqSkill3: number;
reqSkill4: number;
reqSkill5: number;
}

0 comments on commit 045db7f

Please sign in to comment.