index.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /*
  2. eslint-disable @typescript-eslint/naming-convention
  3. */
  4. import { DatabaseManager, EventContext, StoreContext } from '@joystream/hydra-common'
  5. import { Storage } from '../../generated/types/storage'
  6. import {
  7. DistributionBucket,
  8. DistributionBucketFamily,
  9. DistributionBucketOperator,
  10. DistributionBucketOperatorMetadata,
  11. DistributionBucketOperatorStatus,
  12. NodeLocationMetadata,
  13. StorageBag,
  14. StorageBagOwner,
  15. StorageBagOwnerChannel,
  16. StorageBagOwnerCouncil,
  17. StorageBagOwnerMember,
  18. StorageBagOwnerWorkingGroup,
  19. StorageBucket,
  20. StorageBucketOperatorStatusActive,
  21. StorageBucketOperatorStatusInvited,
  22. StorageBucketOperatorStatusMissing,
  23. StorageDataObject,
  24. StorageSystemParameters,
  25. GeoCoordinates,
  26. } from 'query-node/dist/model'
  27. import BN from 'bn.js'
  28. import { getById, getWorkingGroupModuleName, bytesToString } from '../common'
  29. import { BTreeSet } from '@polkadot/types'
  30. import { DataObjectCreationParameters } from '@joystream/types/storage'
  31. import { registry } from '@joystream/types'
  32. import { In } from 'typeorm'
  33. import _ from 'lodash'
  34. import { DataObjectId, BagId, DynamicBagId, StaticBagId } from '@joystream/types/augment/all'
  35. import {
  36. processDistributionBucketFamilyMetadata,
  37. processDistributionOperatorMetadata,
  38. processStorageOperatorMetadata,
  39. } from './metadata'
  40. async function getDataObjectsInBag(
  41. store: DatabaseManager,
  42. bagId: BagId,
  43. dataObjectIds: BTreeSet<DataObjectId>
  44. ): Promise<StorageDataObject[]> {
  45. const dataObjects = await store.getMany(StorageDataObject, {
  46. where: {
  47. id: In(Array.from(dataObjectIds).map((id) => id.toString())),
  48. storageBag: { id: getBagId(bagId) },
  49. },
  50. })
  51. if (dataObjects.length !== Array.from(dataObjectIds).length) {
  52. throw new Error(
  53. `Missing data objects: ${_.difference(
  54. Array.from(dataObjectIds).map((id) => id.toString()),
  55. dataObjects.map((o) => o.id)
  56. )} in bag ${getBagId(bagId)}`
  57. )
  58. }
  59. return dataObjects
  60. }
  61. function getStaticBagOwner(bagId: StaticBagId): typeof StorageBagOwner {
  62. if (bagId.isCouncil) {
  63. return new StorageBagOwnerCouncil()
  64. } else if (bagId.isWorkingGroup) {
  65. const owner = new StorageBagOwnerWorkingGroup()
  66. owner.workingGroupId = getWorkingGroupModuleName(bagId.asWorkingGroup)
  67. return owner
  68. } else {
  69. throw new Error(`Unexpected static bag type: ${bagId.type}`)
  70. }
  71. }
  72. function getDynamicBagOwner(bagId: DynamicBagId) {
  73. if (bagId.isChannel) {
  74. const owner = new StorageBagOwnerChannel()
  75. owner.channelId = bagId.asChannel.toNumber()
  76. return owner
  77. } else if (bagId.isMember) {
  78. const owner = new StorageBagOwnerMember()
  79. owner.memberId = bagId.asMember.toNumber()
  80. return owner
  81. } else {
  82. throw new Error(`Unexpected dynamic bag type: ${bagId.type}`)
  83. }
  84. }
  85. function getStaticBagId(bagId: StaticBagId): string {
  86. if (bagId.isCouncil) {
  87. return `CO`
  88. } else if (bagId.isWorkingGroup) {
  89. return `WG-${bagId.asWorkingGroup.type}`
  90. } else {
  91. throw new Error(`Unexpected static bag type: ${bagId.type}`)
  92. }
  93. }
  94. function getDynamicBagId(bagId: DynamicBagId): string {
  95. if (bagId.isChannel) {
  96. return `CH-${bagId.asChannel.toString()}`
  97. } else if (bagId.isMember) {
  98. return `M-${bagId.asMember.toString()}`
  99. } else {
  100. throw new Error(`Unexpected dynamic bag type: ${bagId.type}`)
  101. }
  102. }
  103. function getBagId(bagId: BagId) {
  104. return bagId.isStatic ? getStaticBagId(bagId.asStatic) : getDynamicBagId(bagId.asDynamic)
  105. }
  106. async function getDynamicBag(
  107. store: DatabaseManager,
  108. bagId: DynamicBagId,
  109. relations?: ('storedBy' | 'distributedBy' | 'objects')[]
  110. ): Promise<StorageBag> {
  111. return getById(store, StorageBag, getDynamicBagId(bagId), relations)
  112. }
  113. async function getStaticBag(
  114. store: DatabaseManager,
  115. bagId: StaticBagId,
  116. relations?: ('storedBy' | 'distributedBy' | 'objects')[]
  117. ): Promise<StorageBag> {
  118. const id = getStaticBagId(bagId)
  119. const bag = await store.get(StorageBag, { where: { id }, relations })
  120. if (!bag) {
  121. console.log(`Creating new static bag: ${id}`)
  122. const newBag = new StorageBag({
  123. id,
  124. owner: getStaticBagOwner(bagId),
  125. })
  126. await store.save<StorageBag>(newBag)
  127. return newBag
  128. }
  129. return bag
  130. }
  131. async function getBag(
  132. store: DatabaseManager,
  133. bagId: BagId,
  134. relations?: ('storedBy' | 'distributedBy' | 'objects')[]
  135. ): Promise<StorageBag> {
  136. return bagId.isStatic
  137. ? getStaticBag(store, bagId.asStatic, relations)
  138. : getDynamicBag(store, bagId.asDynamic, relations)
  139. }
  140. async function getDistributionBucketOperatorWithMetadata(
  141. store: DatabaseManager,
  142. id: string
  143. ): Promise<DistributionBucketOperator> {
  144. const operator = await store.get(DistributionBucketOperator, {
  145. where: { id },
  146. relations: ['metadata', 'metadata.nodeLocation', 'metadata.nodeLocation.coordinates'],
  147. })
  148. if (!operator) {
  149. throw new Error(`DistributionBucketOperator not found by id: ${id}`)
  150. }
  151. return operator
  152. }
  153. async function getStorageBucketWithOperatorMetadata(store: DatabaseManager, id: string): Promise<StorageBucket> {
  154. const bucket = await store.get(StorageBucket, {
  155. where: { id },
  156. relations: ['operatorMetadata', 'operatorMetadata.nodeLocation', 'operatorMetadata.nodeLocation.coordinates'],
  157. })
  158. if (!bucket) {
  159. throw new Error(`StorageBucket not found by id: ${id}`)
  160. }
  161. return bucket
  162. }
  163. async function getDistributionBucketFamilyWithMetadata(
  164. store: DatabaseManager,
  165. id: string
  166. ): Promise<DistributionBucketFamily> {
  167. const family = await store.get(DistributionBucketFamily, {
  168. where: { id },
  169. relations: ['metadata', 'metadata.boundary'],
  170. })
  171. if (!family) {
  172. throw new Error(`DistributionBucketFamily not found by id: ${id}`)
  173. }
  174. return family
  175. }
  176. // BUCKETS
  177. export async function storage_StorageBucketCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  178. const [
  179. bucketId,
  180. invitedWorkerId,
  181. acceptingNewBags,
  182. dataObjectSizeLimit,
  183. dataObjectCountLimit,
  184. ] = new Storage.StorageBucketCreatedEvent(event).params
  185. const storageBucket = new StorageBucket({
  186. id: bucketId.toString(),
  187. acceptingNewBags: acceptingNewBags.isTrue,
  188. dataObjectCountLimit: new BN(dataObjectCountLimit.toString()),
  189. dataObjectsSizeLimit: new BN(dataObjectSizeLimit.toString()),
  190. })
  191. if (invitedWorkerId.isSome) {
  192. const operatorStatus = new StorageBucketOperatorStatusInvited()
  193. operatorStatus.workerId = invitedWorkerId.unwrap().toNumber()
  194. storageBucket.operatorStatus = operatorStatus
  195. } else {
  196. storageBucket.operatorStatus = new StorageBucketOperatorStatusMissing()
  197. }
  198. await store.save<StorageBucket>(storageBucket)
  199. }
  200. export async function storage_StorageOperatorMetadataSet({ event, store }: EventContext & StoreContext): Promise<void> {
  201. const [bucketId, , metadataBytes] = new Storage.StorageOperatorMetadataSetEvent(event).params
  202. const storageBucket = await getStorageBucketWithOperatorMetadata(store, bucketId.toString())
  203. storageBucket.operatorMetadata = await processStorageOperatorMetadata(
  204. store,
  205. storageBucket.operatorMetadata,
  206. metadataBytes
  207. )
  208. await store.save<StorageBucket>(storageBucket)
  209. }
  210. export async function storage_StorageBucketStatusUpdated({ event, store }: EventContext & StoreContext): Promise<void> {
  211. const [bucketId, acceptingNewBags] = new Storage.StorageBucketStatusUpdatedEvent(event).params
  212. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  213. storageBucket.acceptingNewBags = acceptingNewBags.isTrue
  214. await store.save<StorageBucket>(storageBucket)
  215. }
  216. export async function storage_StorageBucketInvitationAccepted({
  217. event,
  218. store,
  219. }: EventContext & StoreContext): Promise<void> {
  220. const [bucketId, workerId] = new Storage.StorageBucketInvitationAcceptedEvent(event).params
  221. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  222. const operatorStatus = new StorageBucketOperatorStatusActive()
  223. operatorStatus.workerId = workerId.toNumber()
  224. storageBucket.operatorStatus = operatorStatus
  225. await store.save<StorageBucket>(storageBucket)
  226. }
  227. export async function storage_StorageBucketInvitationCancelled({
  228. event,
  229. store,
  230. }: EventContext & StoreContext): Promise<void> {
  231. const [bucketId] = new Storage.StorageBucketInvitationCancelledEvent(event).params
  232. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  233. const operatorStatus = new StorageBucketOperatorStatusMissing()
  234. storageBucket.operatorStatus = operatorStatus
  235. await store.save<StorageBucket>(storageBucket)
  236. }
  237. export async function storage_StorageBucketOperatorInvited({
  238. event,
  239. store,
  240. }: EventContext & StoreContext): Promise<void> {
  241. const [bucketId, workerId] = new Storage.StorageBucketOperatorInvitedEvent(event).params
  242. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  243. const operatorStatus = new StorageBucketOperatorStatusInvited()
  244. operatorStatus.workerId = workerId.toNumber()
  245. storageBucket.operatorStatus = operatorStatus
  246. await store.save<StorageBucket>(storageBucket)
  247. }
  248. export async function storage_StorageBucketOperatorRemoved({
  249. event,
  250. store,
  251. }: EventContext & StoreContext): Promise<void> {
  252. const [bucketId] = new Storage.StorageBucketInvitationCancelledEvent(event).params
  253. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  254. const operatorStatus = new StorageBucketOperatorStatusMissing()
  255. storageBucket.operatorStatus = operatorStatus
  256. await store.save<StorageBucket>(storageBucket)
  257. }
  258. export async function storage_StorageBucketsUpdatedForBag({
  259. event,
  260. store,
  261. }: EventContext & StoreContext): Promise<void> {
  262. const [bagId, addedBucketsIds, removedBucketsIds] = new Storage.StorageBucketsUpdatedForBagEvent(event).params
  263. const storageBag = await getBag(store, bagId, ['storedBy'])
  264. storageBag.storedBy = (storageBag.storedBy || [])
  265. .filter((b) => !Array.from(removedBucketsIds).some((id) => id.eq(b.id)))
  266. .concat(Array.from(addedBucketsIds).map((id) => new StorageBucket({ id: id.toString() })))
  267. await store.save<StorageBag>(storageBag)
  268. }
  269. export async function storage_StorageBucketDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  270. const [bucketId] = new Storage.StorageBucketDeletedEvent(event).params
  271. // TODO: Delete or just change status?
  272. // TODO: Cascade remove on db level?
  273. // We shouldn't have to worry about deleting DataObjects, since this is already enforced by the runtime
  274. const storageBucket = await getById(store, StorageBucket, bucketId.toString(), ['storedBags'])
  275. await Promise.all((storageBucket.storedBags || []).map((b) => store.remove<StorageBag>(b)))
  276. await store.remove<StorageBucket>(storageBucket)
  277. }
  278. // DYNAMIC BAGS
  279. export async function storage_DynamicBagCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  280. const [bagId] = new Storage.DynamicBagCreatedEvent(event).params
  281. const storageBag = new StorageBag({
  282. id: getDynamicBagId(bagId),
  283. owner: getDynamicBagOwner(bagId),
  284. })
  285. await store.save<StorageBag>(storageBag)
  286. }
  287. export async function storage_DynamicBagDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  288. const [, bagId] = new Storage.DynamicBagDeletedEvent(event).params
  289. // TODO: Delete or just change status?
  290. // TODO: Cascade remove on db level?
  291. const storageBag = await getDynamicBag(store, bagId, ['objects'])
  292. await Promise.all((storageBag.objects || []).map((o) => store.remove<StorageDataObject>(o)))
  293. await store.remove<StorageBag>(storageBag)
  294. }
  295. // DATA OBJECTS
  296. // Note: "Uploaded" here actually means "created" (the real upload happens later)
  297. export async function storage_DataObjectsUploaded({ event, store }: EventContext & StoreContext): Promise<void> {
  298. const [dataObjectIds, uploadParams] = new Storage.DataObjectsUploadedEvent(event).params
  299. const { bagId, authenticationKey, objectCreationList } = uploadParams
  300. const storageBag = await getBag(store, bagId)
  301. const dataObjects = dataObjectIds.map((objectId, i) => {
  302. const objectParams = new DataObjectCreationParameters(registry, objectCreationList[i].toJSON() as any)
  303. return new StorageDataObject({
  304. id: objectId.toString(),
  305. authenticationKey: bytesToString(authenticationKey),
  306. isAccepted: false,
  307. ipfsHash: bytesToString(objectParams.ipfsContentId),
  308. size: new BN(objectParams.getField('size').toString()),
  309. storageBag,
  310. })
  311. })
  312. await Promise.all(dataObjects.map((o) => store.save<StorageDataObject>(o)))
  313. }
  314. export async function storage_PendingDataObjectsAccepted({ event, store }: EventContext & StoreContext): Promise<void> {
  315. const [, , bagId, dataObjectIds] = new Storage.PendingDataObjectsAcceptedEvent(event).params
  316. const dataObjects = await getDataObjectsInBag(store, bagId, dataObjectIds)
  317. await Promise.all(
  318. dataObjects.map(async (dataObject) => {
  319. dataObject.isAccepted = true
  320. // TODO: Do we still want other storage providers to accept it? How long should the key be valid?
  321. // dataObject.authenticationKey = null as any
  322. await store.save<StorageDataObject>(dataObject)
  323. })
  324. )
  325. }
  326. export async function storage_DataObjectsMoved({ event, store }: EventContext & StoreContext): Promise<void> {
  327. const [srcBagId, destBagId, dataObjectIds] = new Storage.DataObjectsMovedEvent(event).params
  328. const dataObjects = await getDataObjectsInBag(store, srcBagId, dataObjectIds)
  329. const destBag = await getBag(store, destBagId)
  330. await Promise.all(
  331. dataObjects.map(async (dataObject) => {
  332. dataObject.storageBag = destBag
  333. await store.save<StorageDataObject>(dataObject)
  334. })
  335. )
  336. }
  337. export async function storage_DataObjectsDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  338. const [, bagId, dataObjectIds] = new Storage.DataObjectsDeletedEvent(event).params
  339. const dataObjects = await getDataObjectsInBag(store, bagId, dataObjectIds)
  340. // TODO: Delete them or just change status?
  341. // (may not be so optimal if we expect a large amount of data objects)
  342. await Promise.all(dataObjects.map((o) => store.remove<StorageDataObject>(o)))
  343. }
  344. // BLACKLIST
  345. export async function storage_UpdateBlacklist({ event, store }: EventContext & StoreContext): Promise<void> {
  346. const [removedContentIds, addedContentIds] = new Storage.UpdateBlacklistEvent(event).params
  347. const storageSystem = await store.get(StorageSystemParameters, {})
  348. if (!storageSystem) {
  349. throw new Error('StorageSystemParameters entity not found!')
  350. }
  351. storageSystem.blacklist = storageSystem.blacklist
  352. .filter((cid) => !Array.from(removedContentIds).some((id) => id.eq(cid)))
  353. .concat(Array.from(addedContentIds).map((id) => id.toString()))
  354. await store.save<StorageSystemParameters>(storageSystem)
  355. }
  356. export async function storage_DistributionBucketFamilyCreated({
  357. event,
  358. store,
  359. }: EventContext & StoreContext): Promise<void> {
  360. const [familyId] = new Storage.DistributionBucketFamilyCreatedEvent(event).params
  361. const family = new DistributionBucketFamily({
  362. id: familyId.toString(),
  363. })
  364. await store.save<DistributionBucketFamily>(family)
  365. }
  366. export async function storage_DistributionBucketFamilyDeleted({
  367. event,
  368. store,
  369. }: EventContext & StoreContext): Promise<void> {
  370. const [familyId] = new Storage.DistributionBucketFamilyDeletedEvent(event).params
  371. const family = await getById(store, DistributionBucketFamily, familyId.toString())
  372. await store.remove(family)
  373. }
  374. export async function storage_DistributionBucketCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  375. const [familyId, acceptingNewBags, bucketId] = new Storage.DistributionBucketCreatedEvent(event).params
  376. const family = await getById(store, DistributionBucketFamily, familyId.toString())
  377. const bucket = new DistributionBucket({
  378. id: bucketId.toString(),
  379. acceptingNewBags: acceptingNewBags.valueOf(),
  380. distributing: true, // Runtime default
  381. family,
  382. })
  383. await store.save<DistributionBucket>(bucket)
  384. }
  385. export async function storage_DistributionBucketStatusUpdated({
  386. event,
  387. store,
  388. }: EventContext & StoreContext): Promise<void> {
  389. const [, bucketId, acceptingNewBags] = new Storage.DistributionBucketStatusUpdatedEvent(event).params
  390. const bucket = await getById(store, DistributionBucket, bucketId.toString())
  391. bucket.acceptingNewBags = acceptingNewBags.valueOf()
  392. await store.save<DistributionBucket>(bucket)
  393. }
  394. export async function storage_DistributionBucketDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  395. const [, bucketId] = new Storage.DistributionBucketDeletedEvent(event).params
  396. const bucket = await getById(store, DistributionBucket, bucketId.toString())
  397. await store.remove<DistributionBucket>(bucket)
  398. }
  399. export async function storage_DistributionBucketsUpdatedForBag({
  400. event,
  401. store,
  402. }: EventContext & StoreContext): Promise<void> {
  403. const [bagId, , addedBucketsIds, removedBucketsIds] = new Storage.DistributionBucketsUpdatedForBagEvent(event).params
  404. const storageBag = await getBag(store, bagId, ['distributedBy'])
  405. storageBag.distributedBy = (storageBag.distributedBy || [])
  406. .filter((b) => !Array.from(removedBucketsIds).some((id) => id.eq(b.id)))
  407. .concat(Array.from(addedBucketsIds).map((id) => new DistributionBucket({ id: id.toString() })))
  408. await store.save<StorageBag>(storageBag)
  409. }
  410. export async function storage_DistributionBucketModeUpdated({
  411. event,
  412. store,
  413. }: EventContext & StoreContext): Promise<void> {
  414. const [, bucketId, distributing] = new Storage.DistributionBucketModeUpdatedEvent(event).params
  415. const bucket = await getById(store, DistributionBucket, bucketId.toString())
  416. bucket.distributing = distributing.valueOf()
  417. await store.save<DistributionBucket>(bucket)
  418. }
  419. export async function storage_DistributionBucketOperatorInvited({
  420. event,
  421. store,
  422. }: EventContext & StoreContext): Promise<void> {
  423. const [, bucketId, workerId] = new Storage.DistributionBucketOperatorInvitedEvent(event).params
  424. const bucket = await getById(store, DistributionBucket, bucketId.toString())
  425. const invitedOperator = new DistributionBucketOperator({
  426. id: `${bucketId}-${workerId}`,
  427. distributionBucket: bucket,
  428. status: DistributionBucketOperatorStatus.INVITED,
  429. workerId: workerId.toNumber(),
  430. })
  431. await store.save<DistributionBucketOperator>(invitedOperator)
  432. }
  433. export async function storage_DistributionBucketInvitationCancelled({
  434. event,
  435. store,
  436. }: EventContext & StoreContext): Promise<void> {
  437. const [, bucketId, workerId] = new Storage.DistributionBucketOperatorInvitedEvent(event).params
  438. const invitedOperator = await getById(store, DistributionBucketOperator, `${bucketId}-${workerId}`)
  439. await store.remove<DistributionBucketOperator>(invitedOperator)
  440. }
  441. export async function storage_DistributionBucketInvitationAccepted({
  442. event,
  443. store,
  444. }: EventContext & StoreContext): Promise<void> {
  445. const [workerId, , bucketId] = new Storage.DistributionBucketInvitationAcceptedEvent(event).params
  446. const invitedOperator = await getById(store, DistributionBucketOperator, `${bucketId}-${workerId}`)
  447. invitedOperator.status = DistributionBucketOperatorStatus.ACTIVE
  448. await store.save<DistributionBucketOperator>(invitedOperator)
  449. }
  450. export async function storage_DistributionBucketMetadataSet({
  451. event,
  452. store,
  453. }: EventContext & StoreContext): Promise<void> {
  454. const [workerId, , bucketId, metadataBytes] = new Storage.DistributionBucketMetadataSetEvent(event).params
  455. const operator = await getDistributionBucketOperatorWithMetadata(store, `${bucketId}-${workerId}`)
  456. operator.metadata = await processDistributionOperatorMetadata(store, operator.metadata, metadataBytes)
  457. await store.save<DistributionBucketOperator>(operator)
  458. }
  459. export async function storage_DistributionBucketOperatorRemoved({
  460. event,
  461. store,
  462. }: EventContext & StoreContext): Promise<void> {
  463. const [, bucketId, workerId] = new Storage.DistributionBucketOperatorRemovedEvent(event).params
  464. // TODO: Cascade remove
  465. const operator = await getDistributionBucketOperatorWithMetadata(store, `${bucketId}-${workerId}`)
  466. await store.remove<DistributionBucketOperator>(operator)
  467. if (operator.metadata) {
  468. await store.remove<DistributionBucketOperatorMetadata>(operator.metadata)
  469. if (operator.metadata.nodeLocation) {
  470. await store.remove<NodeLocationMetadata>(operator.metadata.nodeLocation)
  471. if (operator.metadata.nodeLocation.coordinates) {
  472. await store.remove<GeoCoordinates>(operator.metadata.nodeLocation.coordinates)
  473. }
  474. }
  475. }
  476. }
  477. export async function storage_DistributionBucketFamilyMetadataSet({
  478. event,
  479. store,
  480. }: EventContext & StoreContext): Promise<void> {
  481. const [familyId, metadataBytes] = new Storage.DistributionBucketFamilyMetadataSetEvent(event).params
  482. const family = await getDistributionBucketFamilyWithMetadata(store, familyId.toString())
  483. family.metadata = await processDistributionBucketFamilyMetadata(store, family.metadata, metadataBytes)
  484. await store.save<DistributionBucketFamily>(family)
  485. }
  486. export async function storage_DistributionBucketsPerBagLimitUpdated({
  487. event,
  488. store,
  489. }: EventContext & StoreContext): Promise<void> {
  490. // To be implemented
  491. }
  492. export async function storage_FamiliesInDynamicBagCreationPolicyUpdated({
  493. event,
  494. store,
  495. }: EventContext & StoreContext): Promise<void> {
  496. // To be implemented
  497. }
  498. export async function storage_StorageBucketVoucherLimitsSet({
  499. event,
  500. store,
  501. }: EventContext & StoreContext): Promise<void> {
  502. // To be implemented
  503. }
  504. export async function storage_UploadingBlockStatusUpdated({
  505. event,
  506. store,
  507. }: EventContext & StoreContext): Promise<void> {
  508. // To be implemented
  509. }
  510. export async function storage_DataObjectPerMegabyteFeeUpdated({
  511. event,
  512. store,
  513. }: EventContext & StoreContext): Promise<void> {
  514. // To be implemented
  515. }
  516. export async function storage_StorageBucketsPerBagLimitUpdated({
  517. event,
  518. store,
  519. }: EventContext & StoreContext): Promise<void> {
  520. // To be implemented
  521. }
  522. export async function storage_StorageBucketsVoucherMaxLimitsUpdated({
  523. event,
  524. store,
  525. }: EventContext & StoreContext): Promise<void> {
  526. // To be implemented
  527. }
  528. export async function storage_VoucherChanged({ event, store }: EventContext & StoreContext): Promise<void> {
  529. // To be implemented
  530. }
  531. export async function storage_NumberOfStorageBucketsInDynamicBagCreationPolicyUpdated({
  532. event,
  533. store,
  534. }: EventContext & StoreContext): Promise<void> {
  535. // To be implemented
  536. }