Browse Source

Distributed buckets - add 'all' config

Leszek Wiesner 3 years ago
parent
commit
f75e6d808a

+ 2 - 1
distributor-node/config.yml

@@ -14,4 +14,5 @@ log:
 storageLimit: 100G
 port: 3334
 keys: [//Alice]
-buckets: [0]
+buckets: 'all'
+workerId: 0

+ 19 - 4
distributor-node/src/api-spec/openapi.yml

@@ -195,7 +195,22 @@ components:
           type: integer
           minimum: 0
     BucketsResponse:
-      type: array
-      items:
-        type: integer
-        minimum: 0
+      oneOf:
+        - type: object
+          required:
+            - "bucketIds"
+          properties:
+            bucketIds:
+              type: array
+              minItems: 1
+              items:
+                type: integer
+                minimum: 0
+        - type: object
+          required:
+            - "allByWorkerId"
+          properties:
+            allByWorkerId:
+              type: integer
+              minimum: 0
+

+ 13 - 6
distributor-node/src/services/networking/NetworkingService.ts

@@ -107,9 +107,15 @@ export class NetworkingService {
     }
     return {
       exists: !!details,
-      isSupported: this.config.buckets.some((bucketId) =>
-        details?.storageBag.distributedBy.map((b) => b.id).includes(bucketId.toString())
-      ),
+      isSupported:
+        (this.config.buckets === 'all' &&
+          details?.storageBag.distributedBy.some((d) =>
+            d.operators.some((o) => o.workerId === this.config.workerId)
+          )) ||
+        (Array.isArray(this.config.buckets) &&
+          this.config.buckets.some((bucketId) =>
+            details?.storageBag.distributedBy.map((b) => b.id).includes(bucketId.toString())
+          )),
       data: details
         ? {
             objectId,
@@ -251,9 +257,10 @@ export class NetworkingService {
   }
 
   async fetchSupportedDataObjects(): Promise<DataObjectData[]> {
-    const data = await this.queryNodeApi.getDistributionBucketsWithObjects(
-      this.config.buckets.map((id) => id.toString())
-    )
+    const data =
+      this.config.buckets === 'all'
+        ? await this.queryNodeApi.getDistributionBucketsWithObjectsByWorkerId(this.config.workerId)
+        : await this.queryNodeApi.getDistributionBucketsWithObjectsByIds(this.config.buckets.map((id) => id.toString()))
     const objectsData: DataObjectData[] = []
     data.forEach((bucket) => {
       bucket.distributedBags.forEach((bag) => {

+ 245 - 15
distributor-node/src/services/networking/distributor-node/generated/api.ts

@@ -21,6 +21,38 @@ import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObj
 // @ts-ignore
 import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base';
 
+/**
+ * @type BucketsResponse
+ * @export
+ */
+export type BucketsResponse = BucketsResponseOneOf | BucketsResponseOneOf1;
+
+/**
+ * 
+ * @export
+ * @interface BucketsResponseOneOf
+ */
+export interface BucketsResponseOneOf {
+    /**
+     * 
+     * @type {Array<number>}
+     * @memberof BucketsResponseOneOf
+     */
+    bucketIds: Array<number>;
+}
+/**
+ * 
+ * @export
+ * @interface BucketsResponseOneOf1
+ */
+export interface BucketsResponseOneOf1 {
+    /**
+     * 
+     * @type {number}
+     * @memberof BucketsResponseOneOf1
+     */
+    allByWorkerId: number;
+}
 /**
  * 
  * @export
@@ -40,6 +72,43 @@ export interface ErrorResponse {
      */
     message: string;
 }
+/**
+ * 
+ * @export
+ * @interface StatusResponse
+ */
+export interface StatusResponse {
+    /**
+     * 
+     * @type {number}
+     * @memberof StatusResponse
+     */
+    objectsInCache: number;
+    /**
+     * 
+     * @type {number}
+     * @memberof StatusResponse
+     */
+    storageLimit: number;
+    /**
+     * 
+     * @type {number}
+     * @memberof StatusResponse
+     */
+    storageUsed: number;
+    /**
+     * 
+     * @type {number}
+     * @memberof StatusResponse
+     */
+    uptime: number;
+    /**
+     * 
+     * @type {number}
+     * @memberof StatusResponse
+     */
+    downloadsInProgress: number;
+}
 
 /**
  * PublicApi - axios parameter creator
@@ -49,15 +118,98 @@ export const PublicApiAxiosParamCreator = function (configuration?: Configuratio
     return {
         /**
          * Returns a media file.
-         * @param {string} objectId Data Object ID
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicAsset: async (objectId: string, options: any = {}): Promise<RequestArgs> => {
-            // verify required parameter 'objectId' is not null or undefined
-            assertParamExists('publicAsset', 'objectId', objectId)
-            const localVarPath = `/asset/{objectId}`
-                .replace(`{${"objectId"}}`, encodeURIComponent(String(objectId)));
+        publicAsset: async (options: any = {}): Promise<RequestArgs> => {
+            const localVarPath = `/asset/{objectId}`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * Returns asset response headers (cache status, content type and/or length, accepted ranges etc.)
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicAssetHead: async (options: any = {}): Promise<RequestArgs> => {
+            const localVarPath = `/asset/{objectId}`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'HEAD', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * Returns list of distributed buckets
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicBuckets: async (options: any = {}): Promise<RequestArgs> => {
+            const localVarPath = `/buckets`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
+            setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * Returns json object describing current node status.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicStatus: async (options: any = {}): Promise<RequestArgs> => {
+            const localVarPath = `/status`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
             let baseOptions;
@@ -92,12 +244,38 @@ export const PublicApiFp = function(configuration?: Configuration) {
     return {
         /**
          * Returns a media file.
-         * @param {string} objectId Data Object ID
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async publicAsset(objectId: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<any>> {
-            const localVarAxiosArgs = await localVarAxiosParamCreator.publicAsset(objectId, options);
+        async publicAsset(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<any>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicAsset(options);
+            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+        },
+        /**
+         * Returns asset response headers (cache status, content type and/or length, accepted ranges etc.)
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async publicAssetHead(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicAssetHead(options);
+            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+        },
+        /**
+         * Returns list of distributed buckets
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async publicBuckets(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BucketsResponse>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicBuckets(options);
+            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+        },
+        /**
+         * Returns json object describing current node status.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async publicStatus(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusResponse>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicStatus(options);
             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
         },
     }
@@ -112,12 +290,35 @@ export const PublicApiFactory = function (configuration?: Configuration, basePat
     return {
         /**
          * Returns a media file.
-         * @param {string} objectId Data Object ID
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicAsset(objectId: string, options?: any): AxiosPromise<any> {
-            return localVarFp.publicAsset(objectId, options).then((request) => request(axios, basePath));
+        publicAsset(options?: any): AxiosPromise<any> {
+            return localVarFp.publicAsset(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * Returns asset response headers (cache status, content type and/or length, accepted ranges etc.)
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicAssetHead(options?: any): AxiosPromise<void> {
+            return localVarFp.publicAssetHead(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * Returns list of distributed buckets
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicBuckets(options?: any): AxiosPromise<BucketsResponse> {
+            return localVarFp.publicBuckets(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * Returns json object describing current node status.
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicStatus(options?: any): AxiosPromise<StatusResponse> {
+            return localVarFp.publicStatus(options).then((request) => request(axios, basePath));
         },
     };
 };
@@ -131,13 +332,42 @@ export const PublicApiFactory = function (configuration?: Configuration, basePat
 export class PublicApi extends BaseAPI {
     /**
      * Returns a media file.
-     * @param {string} objectId Data Object ID
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof PublicApi
      */
-    public publicAsset(objectId: string, options?: any) {
-        return PublicApiFp(this.configuration).publicAsset(objectId, options).then((request) => request(this.axios, this.basePath));
+    public publicAsset(options?: any) {
+        return PublicApiFp(this.configuration).publicAsset(options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * Returns asset response headers (cache status, content type and/or length, accepted ranges etc.)
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof PublicApi
+     */
+    public publicAssetHead(options?: any) {
+        return PublicApiFp(this.configuration).publicAssetHead(options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * Returns list of distributed buckets
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof PublicApi
+     */
+    public publicBuckets(options?: any) {
+        return PublicApiFp(this.configuration).publicBuckets(options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * Returns json object describing current node status.
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof PublicApi
+     */
+    public publicStatus(options?: any) {
+        return PublicApiFp(this.configuration).publicStatus(options).then((request) => request(this.axios, this.basePath));
     }
 }
 

+ 19 - 7
distributor-node/src/services/networking/query-node/api.ts

@@ -6,9 +6,12 @@ import {
   GetDataObjectDetailsQuery,
   GetDataObjectDetailsQueryVariables,
   DistirubtionBucketsWithObjectsFragment,
-  GetDistributionBucketsWithObjectsQuery,
-  GetDistributionBucketsWithObjectsQueryVariables,
-  GetDistributionBucketsWithObjects,
+  GetDistributionBucketsWithObjectsByIdsQuery,
+  GetDistributionBucketsWithObjectsByIdsQueryVariables,
+  GetDistributionBucketsWithObjectsByIds,
+  GetDistributionBucketsWithObjectsByWorkerIdQuery,
+  GetDistributionBucketsWithObjectsByWorkerIdQueryVariables,
+  GetDistributionBucketsWithObjectsByWorkerId,
   StorageBucketOperatorFieldsFragment,
   GetActiveStorageBucketOperatorsDataQuery,
   GetActiveStorageBucketOperatorsDataQueryVariables,
@@ -63,11 +66,20 @@ export class QueryNodeApi {
     )
   }
 
-  public getDistributionBucketsWithObjects(ids: string[]): Promise<DistirubtionBucketsWithObjectsFragment[]> {
+  public getDistributionBucketsWithObjectsByIds(ids: string[]): Promise<DistirubtionBucketsWithObjectsFragment[]> {
     return this.multipleEntitiesQuery<
-      GetDistributionBucketsWithObjectsQuery,
-      GetDistributionBucketsWithObjectsQueryVariables
-    >(GetDistributionBucketsWithObjects, { ids }, 'distributionBuckets')
+      GetDistributionBucketsWithObjectsByIdsQuery,
+      GetDistributionBucketsWithObjectsByIdsQueryVariables
+    >(GetDistributionBucketsWithObjectsByIds, { ids }, 'distributionBuckets')
+  }
+
+  public getDistributionBucketsWithObjectsByWorkerId(
+    workerId: number
+  ): Promise<DistirubtionBucketsWithObjectsFragment[]> {
+    return this.multipleEntitiesQuery<
+      GetDistributionBucketsWithObjectsByWorkerIdQuery,
+      GetDistributionBucketsWithObjectsByWorkerIdQueryVariables
+    >(GetDistributionBucketsWithObjectsByWorkerId, { workerId }, 'distributionBuckets')
   }
 
   public getActiveStorageBucketOperatorsData(): Promise<StorageBucketOperatorFieldsFragment[]> {

+ 22 - 5
distributor-node/src/services/networking/query-node/generated/queries.ts

@@ -1,7 +1,7 @@
 import * as Types from './schema';
 
 import gql from 'graphql-tag';
-export type DataObjectDetailsFragment = { id: string, size: any, ipfsHash: string, isAccepted: boolean, storageBag: { storedBy: Array<{ id: string, operatorMetadata?: Types.Maybe<{ nodeEndpoint?: Types.Maybe<string> }>, operatorStatus: { __typename: 'StorageBucketOperatorStatusMissing' } | { __typename: 'StorageBucketOperatorStatusInvited' } | { __typename: 'StorageBucketOperatorStatusActive' } }>, distributedBy: Array<{ id: string }> } };
+export type DataObjectDetailsFragment = { id: string, size: any, ipfsHash: string, isAccepted: boolean, storageBag: { storedBy: Array<{ id: string, operatorMetadata?: Types.Maybe<{ nodeEndpoint?: Types.Maybe<string> }>, operatorStatus: { __typename: 'StorageBucketOperatorStatusMissing' } | { __typename: 'StorageBucketOperatorStatusInvited' } | { __typename: 'StorageBucketOperatorStatusActive' } }>, distributedBy: Array<{ id: string, operators: Array<{ workerId: number }> }> } };
 
 export type GetDataObjectDetailsQueryVariables = Types.Exact<{
   id: Types.Scalars['ID'];
@@ -12,12 +12,19 @@ export type GetDataObjectDetailsQuery = { storageDataObjectByUniqueInput?: Types
 
 export type DistirubtionBucketsWithObjectsFragment = { id: string, distributedBags: Array<{ objects: Array<{ id: string, size: any, ipfsHash: string }> }> };
 
-export type GetDistributionBucketsWithObjectsQueryVariables = Types.Exact<{
+export type GetDistributionBucketsWithObjectsByIdsQueryVariables = Types.Exact<{
   ids?: Types.Maybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
 }>;
 
 
-export type GetDistributionBucketsWithObjectsQuery = { distributionBuckets: Array<DistirubtionBucketsWithObjectsFragment> };
+export type GetDistributionBucketsWithObjectsByIdsQuery = { distributionBuckets: Array<DistirubtionBucketsWithObjectsFragment> };
+
+export type GetDistributionBucketsWithObjectsByWorkerIdQueryVariables = Types.Exact<{
+  workerId: Types.Scalars['Int'];
+}>;
+
+
+export type GetDistributionBucketsWithObjectsByWorkerIdQuery = { distributionBuckets: Array<DistirubtionBucketsWithObjectsFragment> };
 
 export type StorageBucketOperatorFieldsFragment = { id: string, operatorMetadata?: Types.Maybe<{ nodeEndpoint?: Types.Maybe<string> }> };
 
@@ -44,6 +51,9 @@ export const DataObjectDetails = gql`
     }
     distributedBy {
       id
+      operators {
+        workerId
+      }
     }
   }
 }
@@ -75,13 +85,20 @@ export const GetDataObjectDetails = gql`
   }
 }
     ${DataObjectDetails}`;
-export const GetDistributionBucketsWithObjects = gql`
-    query getDistributionBucketsWithObjects($ids: [ID!]) {
+export const GetDistributionBucketsWithObjectsByIds = gql`
+    query getDistributionBucketsWithObjectsByIds($ids: [ID!]) {
   distributionBuckets(where: {id_in: $ids}) {
     ...DistirubtionBucketsWithObjects
   }
 }
     ${DistirubtionBucketsWithObjects}`;
+export const GetDistributionBucketsWithObjectsByWorkerId = gql`
+    query getDistributionBucketsWithObjectsByWorkerId($workerId: Int!) {
+  distributionBuckets(where: {operators_some: {workerId_eq: $workerId}}) {
+    ...DistirubtionBucketsWithObjects
+  }
+}
+    ${DistirubtionBucketsWithObjects}`;
 export const GetActiveStorageBucketOperatorsData = gql`
     query getActiveStorageBucketOperatorsData {
   storageBuckets(where: {operatorStatus_json: {isTypeOf_eq: "StorageBucketOperatorStatusActive"}, operatorMetadata: {nodeEndpoint_contains: "http"}}, limit: 9999) {

+ 10 - 1
distributor-node/src/services/networking/query-node/queries/queries.graphql

@@ -15,6 +15,9 @@ fragment DataObjectDetails on StorageDataObject {
     }
     distributedBy {
       id
+      operators {
+        workerId
+      }
     }
   }
 }
@@ -36,12 +39,18 @@ fragment DistirubtionBucketsWithObjects on DistributionBucket {
   }
 }
 
-query getDistributionBucketsWithObjects($ids: [ID!]) {
+query getDistributionBucketsWithObjectsByIds($ids: [ID!]) {
   distributionBuckets(where: { id_in: $ids }) {
     ...DistirubtionBucketsWithObjects
   }
 }
 
+query getDistributionBucketsWithObjectsByWorkerId($workerId: Int!) {
+  distributionBuckets(where: { operators_some: { workerId_eq: $workerId } }) {
+    ...DistirubtionBucketsWithObjects
+  }
+}
+
 fragment StorageBucketOperatorFields on StorageBucket {
   id
   operatorMetadata {

+ 90 - 27
distributor-node/src/services/networking/storage-node/generated/api.ts

@@ -51,7 +51,7 @@ export interface InlineResponse201 {
      * @type {string}
      * @memberof InlineResponse201
      */
-    status?: string;
+    id?: string;
 }
 /**
  * 
@@ -135,7 +135,7 @@ export const PublicApiAxiosParamCreator = function (configuration?: Configuratio
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiAuthToken: async (tokenRequest?: TokenRequest, options: any = {}): Promise<RequestArgs> => {
+        publicApiAuthTokenForUploading: async (tokenRequest?: TokenRequest, options: any = {}): Promise<RequestArgs> => {
             const localVarPath = `/authToken`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -168,9 +168,9 @@ export const PublicApiAxiosParamCreator = function (configuration?: Configuratio
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiFiles: async (cid: string, options: any = {}): Promise<RequestArgs> => {
+        publicApiGetFile: async (cid: string, options: any = {}): Promise<RequestArgs> => {
             // verify required parameter 'cid' is not null or undefined
-            assertParamExists('publicApiFiles', 'cid', cid)
+            assertParamExists('publicApiGetFile', 'cid', cid)
             const localVarPath = `/files/{cid}`
                 .replace(`{${"cid"}}`, encodeURIComponent(String(cid)));
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
@@ -186,6 +186,39 @@ export const PublicApiAxiosParamCreator = function (configuration?: Configuratio
 
 
     
+            setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: toPathString(localVarUrlObj),
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * Returns a media file headers.
+         * @param {string} cid Content ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicApiGetFileHeaders: async (cid: string, options: any = {}): Promise<RequestArgs> => {
+            // verify required parameter 'cid' is not null or undefined
+            assertParamExists('publicApiGetFileHeaders', 'cid', cid)
+            const localVarPath = `/files/{cid}`
+                .replace(`{${"cid"}}`, encodeURIComponent(String(cid)));
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+
+            const localVarRequestOptions = { method: 'HEAD', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+
+    
             setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@@ -204,14 +237,14 @@ export const PublicApiAxiosParamCreator = function (configuration?: Configuratio
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiUpload: async (dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options: any = {}): Promise<RequestArgs> => {
+        publicApiUploadFile: async (dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options: any = {}): Promise<RequestArgs> => {
             // verify required parameter 'dataObjectId' is not null or undefined
-            assertParamExists('publicApiUpload', 'dataObjectId', dataObjectId)
+            assertParamExists('publicApiUploadFile', 'dataObjectId', dataObjectId)
             // verify required parameter 'storageBucketId' is not null or undefined
-            assertParamExists('publicApiUpload', 'storageBucketId', storageBucketId)
+            assertParamExists('publicApiUploadFile', 'storageBucketId', storageBucketId)
             // verify required parameter 'bagId' is not null or undefined
-            assertParamExists('publicApiUpload', 'bagId', bagId)
-            const localVarPath = `/upload`;
+            assertParamExists('publicApiUploadFile', 'bagId', bagId)
+            const localVarPath = `/files`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
             let baseOptions;
@@ -273,8 +306,8 @@ export const PublicApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async publicApiAuthToken(tokenRequest?: TokenRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2011>> {
-            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiAuthToken(tokenRequest, options);
+        async publicApiAuthTokenForUploading(tokenRequest?: TokenRequest, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2011>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiAuthTokenForUploading(tokenRequest, options);
             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
         },
         /**
@@ -283,8 +316,18 @@ export const PublicApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async publicApiFiles(cid: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<any>> {
-            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiFiles(cid, options);
+        async publicApiGetFile(cid: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<any>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiGetFile(cid, options);
+            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+        },
+        /**
+         * Returns a media file headers.
+         * @param {string} cid Content ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async publicApiGetFileHeaders(cid: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiGetFileHeaders(cid, options);
             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
         },
         /**
@@ -296,8 +339,8 @@ export const PublicApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async publicApiUpload(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse201>> {
-            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiUpload(dataObjectId, storageBucketId, bagId, file, options);
+        async publicApiUploadFile(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse201>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.publicApiUploadFile(dataObjectId, storageBucketId, bagId, file, options);
             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
         },
     }
@@ -316,8 +359,8 @@ export const PublicApiFactory = function (configuration?: Configuration, basePat
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiAuthToken(tokenRequest?: TokenRequest, options?: any): AxiosPromise<InlineResponse2011> {
-            return localVarFp.publicApiAuthToken(tokenRequest, options).then((request) => request(axios, basePath));
+        publicApiAuthTokenForUploading(tokenRequest?: TokenRequest, options?: any): AxiosPromise<InlineResponse2011> {
+            return localVarFp.publicApiAuthTokenForUploading(tokenRequest, options).then((request) => request(axios, basePath));
         },
         /**
          * Returns a media file.
@@ -325,8 +368,17 @@ export const PublicApiFactory = function (configuration?: Configuration, basePat
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiFiles(cid: string, options?: any): AxiosPromise<any> {
-            return localVarFp.publicApiFiles(cid, options).then((request) => request(axios, basePath));
+        publicApiGetFile(cid: string, options?: any): AxiosPromise<any> {
+            return localVarFp.publicApiGetFile(cid, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * Returns a media file headers.
+         * @param {string} cid Content ID
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        publicApiGetFileHeaders(cid: string, options?: any): AxiosPromise<void> {
+            return localVarFp.publicApiGetFileHeaders(cid, options).then((request) => request(axios, basePath));
         },
         /**
          * Upload data
@@ -337,8 +389,8 @@ export const PublicApiFactory = function (configuration?: Configuration, basePat
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        publicApiUpload(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any): AxiosPromise<InlineResponse201> {
-            return localVarFp.publicApiUpload(dataObjectId, storageBucketId, bagId, file, options).then((request) => request(axios, basePath));
+        publicApiUploadFile(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any): AxiosPromise<InlineResponse201> {
+            return localVarFp.publicApiUploadFile(dataObjectId, storageBucketId, bagId, file, options).then((request) => request(axios, basePath));
         },
     };
 };
@@ -357,8 +409,8 @@ export class PublicApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof PublicApi
      */
-    public publicApiAuthToken(tokenRequest?: TokenRequest, options?: any) {
-        return PublicApiFp(this.configuration).publicApiAuthToken(tokenRequest, options).then((request) => request(this.axios, this.basePath));
+    public publicApiAuthTokenForUploading(tokenRequest?: TokenRequest, options?: any) {
+        return PublicApiFp(this.configuration).publicApiAuthTokenForUploading(tokenRequest, options).then((request) => request(this.axios, this.basePath));
     }
 
     /**
@@ -368,8 +420,19 @@ export class PublicApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof PublicApi
      */
-    public publicApiFiles(cid: string, options?: any) {
-        return PublicApiFp(this.configuration).publicApiFiles(cid, options).then((request) => request(this.axios, this.basePath));
+    public publicApiGetFile(cid: string, options?: any) {
+        return PublicApiFp(this.configuration).publicApiGetFile(cid, options).then((request) => request(this.axios, this.basePath));
+    }
+
+    /**
+     * Returns a media file headers.
+     * @param {string} cid Content ID
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof PublicApi
+     */
+    public publicApiGetFileHeaders(cid: string, options?: any) {
+        return PublicApiFp(this.configuration).publicApiGetFileHeaders(cid, options).then((request) => request(this.axios, this.basePath));
     }
 
     /**
@@ -382,8 +445,8 @@ export class PublicApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof PublicApi
      */
-    public publicApiUpload(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any) {
-        return PublicApiFp(this.configuration).publicApiUpload(dataObjectId, storageBucketId, bagId, file, options).then((request) => request(this.axios, this.basePath));
+    public publicApiUploadFile(dataObjectId: string, storageBucketId: string, bagId: string, file?: any, options?: any) {
+        return PublicApiFp(this.configuration).publicApiUploadFile(dataObjectId, storageBucketId, bagId, file, options).then((request) => request(this.axios, this.basePath));
     }
 }
 

+ 7 - 1
distributor-node/src/services/server/controllers/public.ts

@@ -251,6 +251,12 @@ export class PublicApiController {
   }
 
   public async buckets(req: express.Request, res: express.Response<BucketsResponse>): Promise<void> {
-    res.status(200).json([...this.config.buckets])
+    res
+      .status(200)
+      .json(
+        this.config.buckets === 'all'
+          ? { allByWorkerId: this.config.workerId }
+          : { bucketIds: [...this.config.buckets] }
+      )
   }
 }

+ 9 - 3
distributor-node/src/services/validation/schemas/configSchema.ts

@@ -7,7 +7,7 @@ export const bytesizeRegex = new RegExp(`^[0-9]+(${bytesizeUnits.join('|')})$`)
 
 export const configSchema: JSONSchema4 = {
   type: 'object',
-  required: ['id', 'endpoints', 'directories', 'buckets', 'keys', 'port', 'storageLimit'],
+  required: ['id', 'endpoints', 'directories', 'buckets', 'keys', 'port', 'storageLimit', 'workerId'],
   additionalProperties: false,
   properties: {
     id: { type: 'string' },
@@ -31,9 +31,15 @@ export const configSchema: JSONSchema4 = {
       },
     },
     storageLimit: { type: 'string', pattern: bytesizeRegex.source },
-    port: { type: 'number' },
+    port: { type: 'integer', minimum: 0 },
     keys: { type: 'array', items: { type: 'string' }, minItems: 1 },
-    buckets: { type: 'array', items: { type: 'number' }, minItems: 1 },
+    buckets: {
+      oneOf: [
+        { type: 'array', items: { type: 'integer', minimum: 0 }, minItems: 1 },
+        { type: 'string', enum: ['all'] },
+      ],
+    },
+    workerId: { type: 'integer', minimum: 0 },
   },
 }
 

+ 2 - 1
distributor-node/src/types/generated/ConfigJson.d.ts

@@ -25,5 +25,6 @@ export interface ConfigJson {
   storageLimit: string
   port: number
   keys: [string, ...string[]]
-  buckets: [number, ...number[]]
+  buckets: [number, ...number[]] | 'all'
+  workerId: number
 }

+ 7 - 1
distributor-node/src/types/generated/OpenApi.ts

@@ -33,7 +33,13 @@ export interface components {
       'uptime': number
       'downloadsInProgress': number
     }
-    'BucketsResponse': number[]
+    'BucketsResponse':
+      | {
+          'bucketIds': number[]
+        }
+      | {
+          'allByWorkerId': number
+        }
   }
   parameters: {
     /** Data Object ID */

+ 2 - 2
distributor-node/src/types/generated/OperatorMetadataJson.d.ts

@@ -11,8 +11,8 @@ export interface OperatorMetadataJson {
     countryCode?: string
     city?: string
     coordinates?: {
-      latitude: number
-      longitude: number
+      latitude?: number
+      longitude?: number
     }
   }
   extra?: string