feat: Added resourceExists method to ResourceStore

* feat: added resourceExists method to ResourceStore

* Merge remote-tracking branch 'origin/main' into feat/add-resourceExists-method-to-ResourceStore

* fix: adapted to review

* fix: adapted to review
This commit is contained in:
Arne Vandoorslaer
2021-02-25 13:43:58 +01:00
committed by GitHub
parent e5b7d99da4
commit b3f292d718
24 changed files with 136 additions and 67 deletions

View File

@@ -11,6 +11,10 @@ import type { ResourceStore } from './ResourceStore';
*/
/* eslint-disable @typescript-eslint/no-unused-vars */
export class BaseResourceStore implements ResourceStore {
public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise<boolean> {
throw new NotImplementedHttpError();
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
throw new NotImplementedHttpError();

View File

@@ -67,6 +67,19 @@ export class DataAccessorBasedStore implements ResourceStore {
this.auxiliaryStrategy = auxiliaryStrategy;
}
public async resourceExists(identifier: ResourceIdentifier): Promise<boolean> {
try {
this.validateIdentifier(identifier);
await this.accessor.getMetadata(identifier);
return true;
} catch (error: unknown) {
if (NotFoundHttpError.isInstance(error)) {
return false;
}
throw error;
}
}
public async getRepresentation(identifier: ResourceIdentifier): Promise<Representation> {
this.validateIdentifier(identifier);

View File

@@ -35,6 +35,11 @@ export class LockingResourceStore implements AtomicResourceStore {
this.strategy = strategy;
}
public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise<boolean> {
return this.locks.withReadLock(this.getLockIdentifier(identifier),
async(): Promise<boolean> => this.source.resourceExists(identifier, conditions));
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
return this.lockedRepresentationRun(this.getLockIdentifier(identifier),

View File

@@ -19,6 +19,10 @@ export class MonitoringStore<T extends ResourceStore = ResourceStore>
this.source = source;
}
public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise<boolean> {
return this.source.resourceExists(identifier, conditions);
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
return this.source.getRepresentation(identifier, preferences, conditions);

View File

@@ -17,6 +17,15 @@ export class PassthroughStore<T extends ResourceStore = ResourceStore> implement
this.source = source;
}
public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions): Promise<boolean> {
return this.source.resourceExists(identifier, conditions);
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
return this.source.getRepresentation(identifier, preferences, conditions);
}
public async addResource(container: ResourceIdentifier, representation: Representation,
conditions?: Conditions): Promise<ResourceIdentifier> {
return this.source.addResource(container, representation, conditions);
@@ -27,11 +36,6 @@ export class PassthroughStore<T extends ResourceStore = ResourceStore> implement
return this.source.deleteResource(identifier, conditions);
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
return this.source.getRepresentation(identifier, preferences, conditions);
}
public async modifyResource(identifier: ResourceIdentifier, patch: Patch,
conditions?: Conditions): Promise<ResourceIdentifier[]> {
return this.source.modifyResource(identifier, patch, conditions);

View File

@@ -16,6 +16,15 @@ import type { Conditions } from './Conditions';
* should those be relevant to the store.
*/
export interface ResourceStore {
/**
* Check if a resource exists.
* @param identifier - Identifier of resource to check.
*
* @returns A promise resolving if the resource already exists
*/
resourceExists: (identifier: ResourceIdentifier, conditions?: Conditions) => Promise<boolean>;
/**
* Retrieves a representation of a resource.
* @param identifier - Identifier of the resource to read.

View File

@@ -20,6 +20,11 @@ export class RoutingResourceStore implements ResourceStore {
this.rule = rule;
}
public async resourceExists(identifier: ResourceIdentifier, conditions?: Conditions):
Promise<boolean> {
return (await this.getStore(identifier)).resourceExists(identifier, conditions);
}
public async getRepresentation(identifier: ResourceIdentifier, preferences: RepresentationPreferences,
conditions?: Conditions): Promise<Representation> {
return (await this.getStore(identifier)).getRepresentation(identifier, preferences, conditions);

View File

@@ -1,16 +0,0 @@
import type { ResourceIdentifier } from '../ldp/representation/ResourceIdentifier';
import { NotFoundHttpError } from '../util/errors/NotFoundHttpError';
import type { ResourceStore } from './ResourceStore';
export async function containsResource(store: ResourceStore, identifier: ResourceIdentifier): Promise<boolean> {
try {
const result = await store.getRepresentation(identifier, {});
result.data.destroy();
return true;
} catch (error: unknown) {
if (NotFoundHttpError.isInstance(error)) {
return false;
}
throw error;
}
}

View File

@@ -1,6 +1,5 @@
import type { Representation } from '../../ldp/representation/Representation';
import type { ResourceIdentifier } from '../../ldp/representation/ResourceIdentifier';
import { containsResource } from '../../storage/StoreUtil';
import type { ResourceStore } from '../ResourceStore';
import type { PreferenceSupport } from './PreferenceSupport';
import { RouterRule } from './RouterRule';
@@ -40,8 +39,7 @@ export class ConvertingRouterRule extends RouterRule {
entry.supportChecker.supports({ identifier, representation }));
} else {
// No content-type given so we can only check if one of the stores has data for the identifier
store = await this.findStore(async(entry): Promise<boolean> =>
containsResource(entry.store, input.identifier));
store = await this.findStore(async(entry): Promise<boolean> => entry.store.resourceExists(input.identifier));
}
return store;
}