index.ts 23 KB

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