Browse Source

Support for new bucket family metadata standard

Leszek Wiesner 3 years ago
parent
commit
07320fd7e8

+ 1 - 0
distributor-node/src/command-base/ExitCodes.ts

@@ -2,5 +2,6 @@ enum ExitCodes {
   OK = 0,
   Error = 1,
   ApiError = 200,
+  InvalidInput = 400,
 }
 export = ExitCodes

+ 43 - 2
distributor-node/src/commands/leader/set-bucket-family-metadata.ts

@@ -2,7 +2,14 @@ import fs from 'fs'
 import AccountsCommandBase from '../../command-base/accounts'
 import DefaultCommandBase, { flags } from '../../command-base/default'
 import { ValidationService } from '../../services/validation/ValidationService'
-import { DistributionBucketFamilyMetadata, IDistributionBucketFamilyMetadata } from '@joystream/metadata-protobuf'
+import {
+  DistributionBucketFamilyMetadata,
+  GeographicalArea,
+  IDistributionBucketFamilyMetadata,
+} from '@joystream/metadata-protobuf'
+import { FamilyMetadataJson } from '../../types/generated/FamilyMetadataJson'
+import { isValidCountryCode, isValidSubdivisionCode } from '@joystream/metadata-protobuf/utils'
+import ExitCodes from '../../command-base/ExitCodes'
 
 export default class LeaderSetBucketFamilyMetadata extends AccountsCommandBase {
   static description = `Set/update distribution bucket family metadata.
@@ -22,15 +29,49 @@ export default class LeaderSetBucketFamilyMetadata extends AccountsCommandBase {
     ...DefaultCommandBase.flags,
   }
 
+  parseAndValidateMetadata(input: FamilyMetadataJson): IDistributionBucketFamilyMetadata {
+    const areas: IDistributionBucketFamilyMetadata['areas'] = []
+    input.areas?.forEach((a) => {
+      if ('continentCode' in a && a.continentCode) {
+        areas.push({ continent: GeographicalArea.Continent[a.continentCode] })
+        return
+      }
+      if ('countryCode' in a && a.countryCode) {
+        if (!isValidCountryCode(a.countryCode)) {
+          this.error(`Invalid country code: ${a.countryCode}`, { exit: ExitCodes.InvalidInput })
+        }
+        areas.push({ countryCode: a.countryCode })
+        return
+      }
+      if ('subdivisionCode' in a && a.subdivisionCode) {
+        if (!isValidSubdivisionCode(a.subdivisionCode)) {
+          this.error(`Invalid subdivision code: ${a.subdivisionCode}`, { exit: ExitCodes.InvalidInput })
+        }
+        areas.push({ subdivisionCode: a.subdivisionCode })
+        return
+      }
+      areas.push({})
+    })
+
+    const meta = { ...input, areas }
+    const error = DistributionBucketFamilyMetadata.verify(meta)
+    if (error) {
+      this.error(`Metadata validation failed: ${error}`, { exit: ExitCodes.InvalidInput })
+    }
+
+    return meta
+  }
+
   async run(): Promise<void> {
     const { familyId, input } = this.parse(LeaderSetBucketFamilyMetadata).flags
     const leadKey = await this.getDistributorLeadKey()
 
     const validation = new ValidationService()
-    const metadata: IDistributionBucketFamilyMetadata = validation.validate(
+    const metadataInput: FamilyMetadataJson = validation.validate(
       'FamilyMetadata',
       JSON.parse(fs.readFileSync(input).toString())
     )
+    const metadata = this.parseAndValidateMetadata(metadataInput)
 
     this.log(`Setting bucket family metadata (family: ${familyId})`, metadata)
     await this.sendAndFollowTx(

+ 29 - 6
distributor-node/src/schemas/familyMetadataSchema.ts

@@ -6,15 +6,38 @@ export const familyMetadataSchema: JSONSchema4 = {
   properties: {
     region: { type: 'string' },
     description: { type: 'string' },
-    boundary: {
+    areas: {
       type: 'array',
       items: {
         type: 'object',
-        additionalProperties: false,
-        properties: {
-          latitude: { type: 'number', minimum: -180, maximum: 180 },
-          longitude: { type: 'number', minimum: -180, maximum: 180 },
-        },
+        oneOf: [
+          // Continent:
+          {
+            additionalProperties: false,
+            required: ['continentCode'],
+            properties: { continentCode: { type: 'string', enum: ['AF', 'AN', 'AS', 'EU', 'NA', 'OC', 'SA'] } },
+          },
+          // Country:
+          {
+            additionalProperties: false,
+            required: ['countryCode'],
+            properties: { countryCode: { type: 'string', minLength: 2, maxLength: 2 } },
+          },
+          // Subdivision:
+          {
+            additionalProperties: false,
+            required: ['subdivisionCode'],
+            properties: { subdivisionCode: { type: 'string' } },
+          },
+          // Empty object (for clearing purposes):
+          { additionalProperties: false },
+        ],
+      },
+    },
+    latencyTestTargets: {
+      type: 'array',
+      items: {
+        type: 'string',
       },
     },
   },

+ 13 - 4
distributor-node/src/types/generated/FamilyMetadataJson.d.ts

@@ -8,8 +8,17 @@
 export interface FamilyMetadataJson {
   region?: string
   description?: string
-  boundary?: {
-    latitude?: number
-    longitude?: number
-  }[]
+  areas?: (
+    | {
+        continentCode: 'AF' | 'AN' | 'AS' | 'EU' | 'NA' | 'OC' | 'SA'
+      }
+    | {
+        countryCode: string
+      }
+    | {
+        subdivisionCode: string
+      }
+    | {}
+  )[]
+  latencyTestTargets?: string[]
 }