Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cloud-agnostic/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@itwin/cloud-agnostic-core",
"version": "3.1.0",
"version": "3.1.1",
"description": "Package that allows configuring components loaded by dependency injection",
"keywords": [
"Bentley",
Expand Down
2 changes: 1 addition & 1 deletion common/config/rush/version-policies.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
"definitionName": "lockStepVersion",
"policyName": "lockStepVersionObjectStorage",
"version": "3.1.0",
"version": "3.1.1",
"nextBump": "prerelease"
}
]
2 changes: 1 addition & 1 deletion storage/azure/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@itwin/object-storage-azure",
"version": "3.1.0",
"version": "3.1.1",
"description": "Object storage implementation using Azure Blob Storage",
"keywords": [
"Bentley",
Expand Down
20 changes: 17 additions & 3 deletions storage/azure/src/client/AzureClientStorageBindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,38 @@ import { DependencyConfig, DIContainer } from "@itwin/cloud-agnostic-core";
import {
ClientStorage,
ClientStorageDependency,
RetryOptions,
Types as CoreTypes,
} from "@itwin/object-storage-core";

import { Constants } from "../common";
import { Constants, Types } from "../common";
import { BlockBlobClientWrapperFactory } from "../server/wrappers/BlockBlobClientWrapperFactory";

import { AzureClientStorage } from "./AzureClientStorage";

export interface AzureClientStorageBindingsConfig extends DependencyConfig {
retryOptions?: RetryOptions;
}

export class AzureClientStorageBindings extends ClientStorageDependency {
public readonly dependencyName: string = Constants.storageType;

public override register(
container: DIContainer,
_config?: DependencyConfig
config?: AzureClientStorageBindingsConfig
): void {
container.registerInstance<AzureClientStorageBindingsConfig>(
Types.AzureClient.config,
config ?? { dependencyName: Constants.storageType }
);
container.registerFactory(
CoreTypes.Client.clientWrapperFactory,
() => new BlockBlobClientWrapperFactory()
(c: DIContainer) =>
new BlockBlobClientWrapperFactory(
c.resolve<AzureClientStorageBindingsConfig>(
Types.AzureClient.config
).retryOptions
)
);
container.registerFactory<ClientStorage>(
CoreTypes.Client.clientStorage,
Expand Down
6 changes: 6 additions & 0 deletions storage/azure/src/common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const types = {
AzureServer: {
config: Symbol.for("Types.AzureServer.Config"),
},
AzureClient: {
config: Symbol.for("Types.AzureClient.Config"),
},
AzureFrontend: {
config: Symbol.for("Types.AzureFrontend.Config"),
},
};

export { types as Types };
18 changes: 18 additions & 0 deletions storage/azure/src/common/internal/Helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { StoragePipelineOptions } from "@azure/storage-blob";

import {
assertPrimitiveType,
FalsyValueError,
} from "@itwin/cloud-agnostic-core/lib/internal";
import {
ObjectReference,
RetryOptions,
TransferConfig,
} from "@itwin/object-storage-core/lib/common";
import {
Expand Down Expand Up @@ -42,3 +45,18 @@ export function buildBlobName(reference: ObjectReference): string {
const { relativeDirectory, objectName } = reference;
return (relativeDirectory ? `${relativeDirectory}/` : "") + objectName;
}

export function formatRetryOptions(
retryOptions: RetryOptions
): StoragePipelineOptions {
return {
retryOptions: {
maxTries:
retryOptions.maxRetries !== undefined
? retryOptions.maxRetries + 1
: undefined,
retryDelayInMs: retryOptions.retryDelayMs,
maxRetryDelayInMs: retryOptions.maxRetryDelayMs,
},
};
}
29 changes: 26 additions & 3 deletions storage/azure/src/frontend/AzureFrontendStorageBindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,47 @@
*--------------------------------------------------------------------------------------------*/
import {
FrontendStorage,
FrontendStorageBindingsConfig,
FrontendStorageDependency,
Types as CoreTypes,
} from "@itwin/object-storage-core/lib/frontend";
import { FrontendUrlTransferClient } from "@itwin/object-storage-core/lib/frontend/internal";

import { DIContainer } from "@itwin/cloud-agnostic-core";

import { Constants } from "../common";
import { Constants, Types } from "../common";

import { AzureFrontendStorage } from "./AzureFrontendStorage";
import { FrontendBlockBlobClientWrapperFactory } from "./wrappers";

export class AzureFrontendStorageBindings extends FrontendStorageDependency {
public readonly dependencyName: string = Constants.storageType;

public override register(container: DIContainer): void {
public override register(
container: DIContainer,
config?: FrontendStorageBindingsConfig
): void {
container.registerInstance<FrontendStorageBindingsConfig>(
Types.AzureFrontend.config,
config ?? { dependencyName: Constants.storageType }
);
container.registerFactory<FrontendUrlTransferClient>(
CoreTypes.Frontend.urlTransferClient,
(c: DIContainer) =>
new FrontendUrlTransferClient(
c.resolve<FrontendStorageBindingsConfig>(
Types.AzureFrontend.config
).retryOptions
)
);
container.registerFactory<FrontendBlockBlobClientWrapperFactory>(
CoreTypes.Frontend.clientWrapperFactory,
() => new FrontendBlockBlobClientWrapperFactory()
(c: DIContainer) =>
new FrontendBlockBlobClientWrapperFactory(
c.resolve<FrontendStorageBindingsConfig>(
Types.AzureFrontend.config
).retryOptions
)
);
container.registerFactory<FrontendStorage>(
CoreTypes.Frontend.frontendStorage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
import { BlockBlobClient } from "@azure/storage-blob";

import { instanceOfUrlTransferInput } from "@itwin/object-storage-core/lib/common/internal";
import { UrlTransferInput } from "@itwin/object-storage-core/lib/frontend";
import {
RetryOptions,
UrlTransferInput,
} from "@itwin/object-storage-core/lib/frontend";

import { AzureTransferConfigInput } from "../../common";
import { buildBlobUrl } from "../../common/internal";
import { buildBlobUrl, formatRetryOptions } from "../../common/internal";

import { FrontendBlockBlobClientWrapper } from "./FrontendBlockBlobClientWrapper";

export class FrontendBlockBlobClientWrapperFactory {
public constructor(private readonly _retryOptions: RetryOptions = {}) {}

public create(
input: UrlTransferInput | AzureTransferConfigInput
): FrontendBlockBlobClientWrapper {
const blobClient = new BlockBlobClient(
instanceOfUrlTransferInput(input) ? input.url : buildBlobUrl(input)
instanceOfUrlTransferInput(input) ? input.url : buildBlobUrl(input),
undefined,
formatRetryOptions(this._retryOptions)
);
return new FrontendBlockBlobClientWrapper(blobClient);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
import {
BlobServiceClient,
newPipeline,
StoragePipelineOptions,
StorageSharedKeyCredential,
} from "@azure/storage-blob";

import { RetryOptions } from "@itwin/object-storage-core";

import { formatRetryOptions } from "../../common/internal";

import { BlobServiceClientWrapper } from "./BlobServiceClientWrapper";

export interface AzureBlobServiceConfig {
Expand All @@ -27,20 +28,10 @@ export class BlobServiceClientWrapperFactory {
config.accountName,
config.accountKey
);
const pipelineOptions: StoragePipelineOptions = {
retryOptions: {
maxTries:
this._retryOptions.maxRetries != undefined
? this._retryOptions.maxRetries + 1
: undefined,
retryDelayInMs: this._retryOptions.retryDelayMs,
maxRetryDelayInMs: this._retryOptions.maxRetryDelayMs,
},
};
return new BlobServiceClientWrapper(
new BlobServiceClient(
config.baseUrl,
newPipeline(credential, pipelineOptions)
newPipeline(credential, formatRetryOptions(this._retryOptions))
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@ import { BlockBlobClient } from "@azure/storage-blob";

import { instanceOfUrlTransferInput } from "@itwin/object-storage-core/lib/common/internal";

import { UrlTransferInput } from "@itwin/object-storage-core";
import { RetryOptions, UrlTransferInput } from "@itwin/object-storage-core";

import { AzureTransferConfigInput } from "../../common";
import { buildBlobUrl } from "../../common/internal";
import { buildBlobUrl, formatRetryOptions } from "../../common/internal";

import { BlockBlobClientWrapper } from "./BlockBlobClientWrapper";

export class BlockBlobClientWrapperFactory {
public constructor(private readonly _retryOptions: RetryOptions = {}) {}

public create(
input: UrlTransferInput | AzureTransferConfigInput
): BlockBlobClientWrapper {
const blobClient = new BlockBlobClient(
instanceOfUrlTransferInput(input) ? input.url : buildBlobUrl(input)
instanceOfUrlTransferInput(input) ? input.url : buildBlobUrl(input),
undefined,
formatRetryOptions(this._retryOptions)
);
return new BlockBlobClientWrapper(blobClient);
}
Expand Down
2 changes: 1 addition & 1 deletion storage/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@itwin/object-storage-core",
"version": "3.1.0",
"version": "3.1.1",
"description": "Core generic object storage interfaces",
"keywords": [
"Bentley",
Expand Down
1 change: 1 addition & 0 deletions storage/core/src/common/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const types = {
Frontend: {
clientWrapperFactory: Symbol.for("Types.Frontend.clientWrapperFactory"),
frontendStorage: Symbol.for("Types.Client.frontendStorage"),
urlTransferClient: Symbol.for("Types.Frontend.urlTransferClient"),
},
Server: {
presignedUrlProvider: Symbol.for("Types.Server.presignedUrlProvider"),
Expand Down
7 changes: 7 additions & 0 deletions storage/core/src/frontend/FrontendInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { DependencyConfig } from "@itwin/cloud-agnostic-core";

import {
ConfigTransferInput,
Metadata,
MultipartUploadOptions,
ObjectReference,
TransferConfig,
UrlTransferInput,
RetryOptions,
} from "../common";

export type FrontendTransferType = "buffer" | "stream";
export type FrontendTransferData = ArrayBuffer | ReadableStream;
export type FrontendMultipartUploadData = ReadableStream;

export interface FrontendStorageBindingsConfig extends DependencyConfig {
retryOptions?: RetryOptions;
}

export interface FrontendUrlDownloadInput extends UrlTransferInput {
transferType: FrontendTransferType;
}
Expand Down
5 changes: 3 additions & 2 deletions storage/core/src/frontend/FrontendStorageDependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {

import { Types } from "../common";

import { FrontendStorageBindingsConfig } from "./FrontendInterfaces";
import { FrontendStorage } from "./FrontendStorage";
import { StrategyFrontendStorage } from "./StrategyFrontendStorage";

Expand All @@ -22,10 +23,10 @@ export abstract class FrontendStorageDependency extends StrategyDependency {

public override registerStrategy(
container: DIContainer,
config: DependencyConfig
config: FrontendStorageBindingsConfig
): void {
if (!config.dependencyName)
throw new ConfigError<DependencyConfig>("dependencyName");
throw new ConfigError<FrontendStorageBindingsConfig>("dependencyName");

container.registerFactory<FrontendStorage>(
Types.Frontend.frontendStorage,
Expand Down
Loading
Loading