cleanup preference repo
This commit is contained in:
parent
ba512c2e5b
commit
34eeb11930
|
@ -2,13 +2,13 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||
import {
|
||||
DecodedPref,
|
||||
PrefValueType,
|
||||
PrefValueTypeStrings,
|
||||
PrefValueTypeStrings
|
||||
} from 'picsur-shared/dist/dto/preferences.dto';
|
||||
import {
|
||||
AsyncFailable,
|
||||
Fail,
|
||||
Failable,
|
||||
HasFailed,
|
||||
HasFailed
|
||||
} from 'picsur-shared/dist/types';
|
||||
|
||||
type Enum = Record<string, string>;
|
||||
|
@ -16,7 +16,7 @@ type EnumValue<E> = E[keyof E];
|
|||
type PrefValueTypeType<E extends Enum> = {
|
||||
[key in EnumValue<E>]: PrefValueTypeStrings;
|
||||
};
|
||||
type KeyValuePref = {
|
||||
type EncodedPref = {
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
|
@ -25,8 +25,13 @@ type KeyValuePref = {
|
|||
export class PreferenceCommonService {
|
||||
private readonly logger = new Logger('PreferenceCommonService');
|
||||
|
||||
public validateAndUnpackPref<E extends Enum>(
|
||||
preference: KeyValuePref,
|
||||
// Preferences values are only validated upon encoding, not decoding
|
||||
// The preference keys are always validated
|
||||
|
||||
// E is either the SysPreference or the UsrPreference enum
|
||||
// the pref value types is the object containing the type of each key in E
|
||||
public DecodePref<E extends Enum>(
|
||||
preference: EncodedPref,
|
||||
prefType: E,
|
||||
prefValueTypes: PrefValueTypeType<E>,
|
||||
): Failable<DecodedPref> {
|
||||
|
@ -58,17 +63,17 @@ export class PreferenceCommonService {
|
|||
return Fail('Invalid preference value');
|
||||
}
|
||||
|
||||
public async validatePref<E extends Enum>(
|
||||
public async EncodePref<E extends Enum>(
|
||||
key: string,
|
||||
value: PrefValueType,
|
||||
prefType: E,
|
||||
prefValueTypes: PrefValueTypeType<E>,
|
||||
): AsyncFailable<KeyValuePref> {
|
||||
): AsyncFailable<EncodedPref> {
|
||||
const validatedKey = this.validatePrefKey(key, prefType);
|
||||
if (HasFailed(validatedKey)) return validatedKey;
|
||||
|
||||
const valueType = prefValueTypes[validatedKey];
|
||||
const validatedValue = this.validateAndPackPrefValue(value, valueType);
|
||||
const validatedValue = this.encodePrefValue(value, valueType);
|
||||
if (HasFailed(validatedValue)) return validatedValue;
|
||||
|
||||
return {
|
||||
|
@ -89,7 +94,7 @@ export class PreferenceCommonService {
|
|||
return key as V;
|
||||
}
|
||||
|
||||
public validateAndPackPrefValue(
|
||||
public encodePrefValue(
|
||||
value: PrefValueType,
|
||||
expectedType: PrefValueTypeStrings,
|
||||
): Failable<string> {
|
||||
|
|
|
@ -5,8 +5,9 @@ import { UsrPreference } from 'picsur-shared/dist/dto/usr-preferences.enum';
|
|||
import { generateRandomString } from 'picsur-shared/dist/util/random';
|
||||
import { EarlyJwtConfigService } from '../../config/early/early-jwt.config.service';
|
||||
|
||||
// This specific service is used to store default values for system preferences
|
||||
// This specific service holds the default values for system and user preferences
|
||||
// It needs to be in a service because the values depend on the environment
|
||||
// This environment is not loaded outside of services
|
||||
|
||||
@Injectable()
|
||||
export class PreferenceDefaultsService {
|
||||
|
|
|
@ -36,7 +36,7 @@ export class SysPreferenceService {
|
|||
value: PrefValueType,
|
||||
): AsyncFailable<DecodedSysPref> {
|
||||
// Validate
|
||||
let sysPreference = await this.validateSysPref(key, value);
|
||||
let sysPreference = await this.encodeSysPref(key, value);
|
||||
if (HasFailed(sysPreference)) return sysPreference;
|
||||
|
||||
// Set
|
||||
|
@ -49,7 +49,6 @@ export class SysPreferenceService {
|
|||
return Fail(e);
|
||||
}
|
||||
|
||||
// Return
|
||||
return {
|
||||
key: sysPreference.key,
|
||||
value,
|
||||
|
@ -63,8 +62,9 @@ export class SysPreferenceService {
|
|||
let validatedKey = this.prefCommon.validatePrefKey(key, SysPreference);
|
||||
if (HasFailed(validatedKey)) return validatedKey;
|
||||
|
||||
// See the comment in 'mutex-fallback.ts' for why we are using a mutex here
|
||||
return MutexFallBack(
|
||||
'fetchSysPrefrence',
|
||||
`fetchSysPrefrence-${key}`,
|
||||
async () => {
|
||||
let existing: ESysPreferenceBackend | null;
|
||||
try {
|
||||
|
@ -84,7 +84,7 @@ export class SysPreferenceService {
|
|||
}
|
||||
|
||||
// Return
|
||||
return this.prefCommon.validateAndUnpackPref(
|
||||
return this.prefCommon.DecodePref(
|
||||
result.data,
|
||||
SysPreference,
|
||||
SysPreferenceValueTypes,
|
||||
|
@ -106,6 +106,7 @@ export class SysPreferenceService {
|
|||
return this.getPreferencePinned(key, 'boolean') as AsyncFailable<boolean>;
|
||||
}
|
||||
|
||||
// Get a preference that will be pinned to a specified type
|
||||
private async getPreferencePinned(
|
||||
key: string,
|
||||
type: PrefValueTypeStrings,
|
||||
|
@ -137,11 +138,11 @@ export class SysPreferenceService {
|
|||
return this.setPreference(key, this.defaultsService.sysDefaults[key]());
|
||||
}
|
||||
|
||||
private async validateSysPref(
|
||||
private async encodeSysPref(
|
||||
key: string,
|
||||
value: PrefValueType,
|
||||
): AsyncFailable<ESysPreferenceBackend> {
|
||||
const validated = await this.prefCommon.validatePref(
|
||||
const validated = await this.prefCommon.EncodePref(
|
||||
key,
|
||||
value,
|
||||
SysPreference,
|
||||
|
|
|
@ -37,7 +37,7 @@ export class UsrPreferenceService {
|
|||
value: PrefValueType,
|
||||
): AsyncFailable<DecodedUsrPref> {
|
||||
// Validate
|
||||
let usrPreference = await this.validatePref(userid, key, value);
|
||||
let usrPreference = await this.encodeUsrPref(userid, key, value);
|
||||
if (HasFailed(usrPreference)) return usrPreference;
|
||||
|
||||
// Set
|
||||
|
@ -68,6 +68,7 @@ export class UsrPreferenceService {
|
|||
let validatedKey = this.prefCommon.validatePrefKey(key, UsrPreference);
|
||||
if (HasFailed(validatedKey)) return validatedKey;
|
||||
|
||||
// See the comment in 'mutex-fallback.ts' for why we are using a mutex here
|
||||
return MutexFallBack(
|
||||
'fetchUsrPrefrence',
|
||||
async () => {
|
||||
|
@ -89,7 +90,7 @@ export class UsrPreferenceService {
|
|||
}
|
||||
|
||||
// Return
|
||||
const unpacked = this.prefCommon.validateAndUnpackPref(
|
||||
const unpacked = this.prefCommon.DecodePref(
|
||||
result.data,
|
||||
UsrPreference,
|
||||
UsrPreferenceValueTypes,
|
||||
|
@ -137,6 +138,7 @@ export class UsrPreferenceService {
|
|||
) as AsyncFailable<boolean>;
|
||||
}
|
||||
|
||||
// Get a preference that will be pinned to a specified type
|
||||
private async getPreferencePinned(
|
||||
userid: string,
|
||||
key: string,
|
||||
|
@ -176,12 +178,12 @@ export class UsrPreferenceService {
|
|||
);
|
||||
}
|
||||
|
||||
private async validatePref(
|
||||
private async encodeUsrPref(
|
||||
userid: string,
|
||||
key: string,
|
||||
value: PrefValueType,
|
||||
): AsyncFailable<EUsrPreferenceBackend> {
|
||||
const validated = await this.prefCommon.validatePref(
|
||||
const validated = await this.prefCommon.EncodePref(
|
||||
key,
|
||||
value,
|
||||
UsrPreference,
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
This function is necessary to make sure that a default isnt generated multiple times at the same time.
|
||||
This function is necessary to make sure that a default isn't generated multiple times at the same time.
|
||||
Doing that will cause errors.
|
||||
|
||||
An example is the jwt secret value, its value is requested aroun 3 times at the same time while starting.
|
||||
An example is the jwt secret value, it's value is requested around 3 times at the same time while starting.
|
||||
So when the program was started for the first time, each request returned a different secret.
|
||||
|
||||
This function will first try and see if its first function returns a value, if it does, it will return that value.
|
||||
This function will try and see if its first function returns a value, if it does, it will return that value.
|
||||
(A Failure object will be seen as a value, only null and undefined are counted as non-values)
|
||||
If not it will execute a fallback function, which usually is a function that populates a default value.
|
||||
After that is done it will retry the first function again.
|
||||
*/
|
||||
|
@ -20,21 +21,22 @@ export async function MutexFallBack<
|
|||
const try_it = await mainFunc();
|
||||
if (try_it !== undefined && try_it !== null) return try_it;
|
||||
|
||||
// Check if a fallback is already running, if so wait on that
|
||||
if (fallBackMap[key] !== undefined) {
|
||||
await fallBackMap[key];
|
||||
|
||||
// When it is done, try again
|
||||
return MutexFallBack(key, mainFunc, fallBackFunc);
|
||||
}
|
||||
|
||||
// No fallback is running, start one
|
||||
const fallBackPromise = fallBackFunc();
|
||||
|
||||
// Save the running fallback, and make sure it is cleared when it is done
|
||||
fallBackMap[key] = fallBackPromise;
|
||||
fallBackMap[key]
|
||||
.then(() => {
|
||||
delete fallBackMap[key];
|
||||
})
|
||||
.catch(() => {
|
||||
delete fallBackMap[key];
|
||||
});
|
||||
fallBackMap[key].finally(() => {
|
||||
delete fallBackMap[key];
|
||||
});
|
||||
|
||||
return fallBackPromise;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue