index.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /*
  2. eslint-disable @typescript-eslint/naming-convention
  3. */
  4. import { 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. StorageBucket,
  15. StorageBucketOperatorStatusActive,
  16. StorageBucketOperatorStatusInvited,
  17. StorageBucketOperatorStatusMissing,
  18. StorageDataObject,
  19. StorageSystemParameters,
  20. GeoCoordinates,
  21. } from 'query-node/dist/model'
  22. import BN from 'bn.js'
  23. import { getById, inconsistentState } from '../common'
  24. import {
  25. processDistributionBucketFamilyMetadata,
  26. processDistributionOperatorMetadata,
  27. processStorageOperatorMetadata,
  28. } from './metadata'
  29. import {
  30. createDataObjects,
  31. getStorageSystem,
  32. removeDataObject,
  33. getStorageBucketWithOperatorMetadata,
  34. getBag,
  35. getDynamicBagId,
  36. getDynamicBagOwner,
  37. getDataObjectsInBag,
  38. getDynamicBag,
  39. getDistributionBucketFamilyWithMetadata,
  40. getDistributionBucketOperatorWithMetadata,
  41. distributionBucketId,
  42. distributionOperatorId,
  43. distributionBucketIdByFamilyAndIndex,
  44. } from './utils'
  45. // STORAGE BUCKETS
  46. export async function storage_StorageBucketCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  47. const [
  48. bucketId,
  49. invitedWorkerId,
  50. acceptingNewBags,
  51. dataObjectSizeLimit,
  52. dataObjectCountLimit,
  53. ] = new Storage.StorageBucketCreatedEvent(event).params
  54. const storageBucket = new StorageBucket({
  55. id: bucketId.toString(),
  56. acceptingNewBags: acceptingNewBags.isTrue,
  57. dataObjectCountLimit: new BN(dataObjectCountLimit.toString()),
  58. dataObjectsSizeLimit: new BN(dataObjectSizeLimit.toString()),
  59. dataObjectsCount: new BN(0),
  60. dataObjectsSize: new BN(0),
  61. })
  62. if (invitedWorkerId.isSome) {
  63. const operatorStatus = new StorageBucketOperatorStatusInvited()
  64. operatorStatus.workerId = invitedWorkerId.unwrap().toNumber()
  65. storageBucket.operatorStatus = operatorStatus
  66. } else {
  67. storageBucket.operatorStatus = new StorageBucketOperatorStatusMissing()
  68. }
  69. await store.save<StorageBucket>(storageBucket)
  70. }
  71. export async function storage_StorageOperatorMetadataSet({ event, store }: EventContext & StoreContext): Promise<void> {
  72. const [bucketId, , metadataBytes] = new Storage.StorageOperatorMetadataSetEvent(event).params
  73. const storageBucket = await getStorageBucketWithOperatorMetadata(store, bucketId.toString())
  74. storageBucket.operatorMetadata = await processStorageOperatorMetadata(
  75. store,
  76. storageBucket.operatorMetadata,
  77. metadataBytes
  78. )
  79. await store.save<StorageBucket>(storageBucket)
  80. }
  81. export async function storage_StorageBucketStatusUpdated({ event, store }: EventContext & StoreContext): Promise<void> {
  82. const [bucketId, acceptingNewBags] = new Storage.StorageBucketStatusUpdatedEvent(event).params
  83. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  84. storageBucket.acceptingNewBags = acceptingNewBags.isTrue
  85. await store.save<StorageBucket>(storageBucket)
  86. }
  87. export async function storage_StorageBucketInvitationAccepted({
  88. event,
  89. store,
  90. }: EventContext & StoreContext): Promise<void> {
  91. const [bucketId, workerId, transactorAccountId] = new Storage.StorageBucketInvitationAcceptedEvent(event).params
  92. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  93. const operatorStatus = new StorageBucketOperatorStatusActive()
  94. operatorStatus.workerId = workerId.toNumber()
  95. operatorStatus.transactorAccountId = transactorAccountId.toString()
  96. storageBucket.operatorStatus = operatorStatus
  97. await store.save<StorageBucket>(storageBucket)
  98. }
  99. export async function storage_StorageBucketInvitationCancelled({
  100. event,
  101. store,
  102. }: EventContext & StoreContext): Promise<void> {
  103. const [bucketId] = new Storage.StorageBucketInvitationCancelledEvent(event).params
  104. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  105. const operatorStatus = new StorageBucketOperatorStatusMissing()
  106. storageBucket.operatorStatus = operatorStatus
  107. await store.save<StorageBucket>(storageBucket)
  108. }
  109. export async function storage_StorageBucketOperatorInvited({
  110. event,
  111. store,
  112. }: EventContext & StoreContext): Promise<void> {
  113. const [bucketId, workerId] = new Storage.StorageBucketOperatorInvitedEvent(event).params
  114. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  115. const operatorStatus = new StorageBucketOperatorStatusInvited()
  116. operatorStatus.workerId = workerId.toNumber()
  117. storageBucket.operatorStatus = operatorStatus
  118. await store.save<StorageBucket>(storageBucket)
  119. }
  120. export async function storage_StorageBucketOperatorRemoved({
  121. event,
  122. store,
  123. }: EventContext & StoreContext): Promise<void> {
  124. const [bucketId] = new Storage.StorageBucketInvitationCancelledEvent(event).params
  125. const storageBucket = await getById(store, StorageBucket, bucketId.toString())
  126. const operatorStatus = new StorageBucketOperatorStatusMissing()
  127. storageBucket.operatorStatus = operatorStatus
  128. await store.save<StorageBucket>(storageBucket)
  129. }
  130. export async function storage_StorageBucketsUpdatedForBag({
  131. event,
  132. store,
  133. }: EventContext & StoreContext): Promise<void> {
  134. const [bagId, addedBucketsSet, removedBucketsSet] = new Storage.StorageBucketsUpdatedForBagEvent(event).params
  135. // Get or create bag
  136. const storageBag = await getBag(store, bagId, ['storageBuckets'])
  137. const removedBucketsIds = Array.from(removedBucketsSet).map((id) => id.toString())
  138. const addedBucketsIds = Array.from(addedBucketsSet).map((id) => id.toString())
  139. storageBag.storageBuckets = (storageBag.storageBuckets || [])
  140. .filter((bucket) => !removedBucketsIds.includes(bucket.id))
  141. .concat(addedBucketsIds.map((id) => new StorageBucket({ id })))
  142. await store.save<StorageBag>(storageBag)
  143. }
  144. export async function storage_VoucherChanged({ event, store }: EventContext & StoreContext): Promise<void> {
  145. const [bucketId, voucher] = new Storage.VoucherChangedEvent(event).params
  146. const bucket = await getById(store, StorageBucket, bucketId.toString())
  147. bucket.dataObjectCountLimit = voucher.objectsLimit
  148. bucket.dataObjectsSizeLimit = voucher.sizeLimit
  149. bucket.dataObjectsCount = voucher.objectsUsed
  150. bucket.dataObjectsSize = voucher.sizeUsed
  151. await store.save<StorageBucket>(bucket)
  152. }
  153. export async function storage_StorageBucketVoucherLimitsSet({
  154. event,
  155. store,
  156. }: EventContext & StoreContext): Promise<void> {
  157. const [bucketId, sizeLimit, countLimit] = new Storage.StorageBucketVoucherLimitsSetEvent(event).params
  158. const bucket = await getById(store, StorageBucket, bucketId.toString())
  159. bucket.dataObjectsSizeLimit = sizeLimit
  160. bucket.dataObjectCountLimit = countLimit
  161. await store.save<StorageBucket>(bucket)
  162. }
  163. export async function storage_StorageBucketDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  164. const [bucketId] = new Storage.StorageBucketDeletedEvent(event).params
  165. // TODO: Cascade remove on db level (would require changes in Hydra / comitting autogenerated files)
  166. const storageBucket = await store.get(StorageBucket, {
  167. where: { id: bucketId.toString() },
  168. relations: ['bags', 'bags.storageBuckets'],
  169. })
  170. if (!storageBucket) {
  171. inconsistentState(`Storage bucket by id ${bucketId.toString()} not found!`)
  172. }
  173. // Remove relations
  174. await Promise.all(
  175. (storageBucket.bags || []).map((bag) => {
  176. bag.storageBuckets = (bag.storageBuckets || []).filter((bucket) => bucket.id !== bucketId.toString())
  177. return store.save<StorageBag>(bag)
  178. })
  179. )
  180. await store.remove<StorageBucket>(storageBucket)
  181. }
  182. // DYNAMIC BAGS
  183. export async function storage_DynamicBagCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  184. const [bagId, , storageBucketIdsSet, distributionBucketIdsSet] = new Storage.DynamicBagCreatedEvent(event).params
  185. const storageBag = new StorageBag({
  186. id: getDynamicBagId(bagId),
  187. owner: getDynamicBagOwner(bagId),
  188. storageBuckets: Array.from(storageBucketIdsSet).map((id) => new StorageBucket({ id: id.toString() })),
  189. distributionBuckets: Array.from(distributionBucketIdsSet).map(
  190. (id) => new DistributionBucket({ id: distributionBucketId(id) })
  191. ),
  192. })
  193. await store.save<StorageBag>(storageBag)
  194. }
  195. export async function storage_DynamicBagDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  196. const [, bagId] = new Storage.DynamicBagDeletedEvent(event).params
  197. const storageBag = await getDynamicBag(store, bagId, ['objects'])
  198. await store.remove<StorageBag>(storageBag)
  199. }
  200. // DATA OBJECTS
  201. // Note: "Uploaded" here actually means "created" (the real upload happens later)
  202. export async function storage_DataObjectsUploaded({ event, store }: EventContext & StoreContext): Promise<void> {
  203. const [dataObjectIds, uploadParams, deletionPrize] = new Storage.DataObjectsUploadedEvent(event).params
  204. await createDataObjects(store, uploadParams, deletionPrize, dataObjectIds)
  205. }
  206. export async function storage_PendingDataObjectsAccepted({ event, store }: EventContext & StoreContext): Promise<void> {
  207. const [, , bagId, dataObjectIds] = new Storage.PendingDataObjectsAcceptedEvent(event).params
  208. const dataObjects = await getDataObjectsInBag(store, bagId, dataObjectIds)
  209. await Promise.all(
  210. dataObjects.map(async (dataObject) => {
  211. dataObject.isAccepted = true
  212. await store.save<StorageDataObject>(dataObject)
  213. })
  214. )
  215. }
  216. export async function storage_DataObjectsMoved({ event, store }: EventContext & StoreContext): Promise<void> {
  217. const [srcBagId, destBagId, dataObjectIds] = new Storage.DataObjectsMovedEvent(event).params
  218. const dataObjects = await getDataObjectsInBag(store, srcBagId, dataObjectIds)
  219. const destBag = await getBag(store, destBagId)
  220. await Promise.all(
  221. dataObjects.map(async (dataObject) => {
  222. dataObject.storageBag = destBag
  223. await store.save<StorageDataObject>(dataObject)
  224. })
  225. )
  226. }
  227. export async function storage_DataObjectsDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  228. const [, bagId, dataObjectIds] = new Storage.DataObjectsDeletedEvent(event).params
  229. const dataObjects = await getDataObjectsInBag(store, bagId, dataObjectIds)
  230. await Promise.all(dataObjects.map((o) => removeDataObject(store, o)))
  231. }
  232. // DISTRIBUTION FAMILY
  233. export async function storage_DistributionBucketFamilyCreated({
  234. event,
  235. store,
  236. }: EventContext & StoreContext): Promise<void> {
  237. const [familyId] = new Storage.DistributionBucketFamilyCreatedEvent(event).params
  238. const family = new DistributionBucketFamily({
  239. id: familyId.toString(),
  240. })
  241. await store.save<DistributionBucketFamily>(family)
  242. }
  243. export async function storage_DistributionBucketFamilyMetadataSet({
  244. event,
  245. store,
  246. }: EventContext & StoreContext): Promise<void> {
  247. const [familyId, metadataBytes] = new Storage.DistributionBucketFamilyMetadataSetEvent(event).params
  248. const family = await getDistributionBucketFamilyWithMetadata(store, familyId.toString())
  249. family.metadata = await processDistributionBucketFamilyMetadata(store, family.metadata, metadataBytes)
  250. await store.save<DistributionBucketFamily>(family)
  251. }
  252. export async function storage_DistributionBucketFamilyDeleted({
  253. event,
  254. store,
  255. }: EventContext & StoreContext): Promise<void> {
  256. const [familyId] = new Storage.DistributionBucketFamilyDeletedEvent(event).params
  257. const family = await getById(store, DistributionBucketFamily, familyId.toString())
  258. await store.remove(family)
  259. }
  260. // DISTRIBUTION BUCKET
  261. export async function storage_DistributionBucketCreated({ event, store }: EventContext & StoreContext): Promise<void> {
  262. const [familyId, acceptingNewBags, bucketId] = new Storage.DistributionBucketCreatedEvent(event).params
  263. const family = await getById(store, DistributionBucketFamily, familyId.toString())
  264. const bucket = new DistributionBucket({
  265. id: distributionBucketId(bucketId),
  266. bucketIndex: bucketId.distribution_bucket_index.toNumber(),
  267. acceptingNewBags: acceptingNewBags.valueOf(),
  268. distributing: true, // Runtime default
  269. family,
  270. })
  271. await store.save<DistributionBucket>(bucket)
  272. }
  273. export async function storage_DistributionBucketStatusUpdated({
  274. event,
  275. store,
  276. }: EventContext & StoreContext): Promise<void> {
  277. const [bucketId, acceptingNewBags] = new Storage.DistributionBucketStatusUpdatedEvent(event).params
  278. const bucket = await getById(store, DistributionBucket, distributionBucketId(bucketId))
  279. bucket.acceptingNewBags = acceptingNewBags.valueOf()
  280. await store.save<DistributionBucket>(bucket)
  281. }
  282. export async function storage_DistributionBucketDeleted({ event, store }: EventContext & StoreContext): Promise<void> {
  283. const [bucketId] = new Storage.DistributionBucketDeletedEvent(event).params
  284. // TODO: Cascade remove on db level (would require changes in Hydra / comitting autogenerated files)
  285. const distributionBucket = await store.get(DistributionBucket, {
  286. where: { id: distributionBucketId(bucketId) },
  287. relations: ['bags', 'bags.distributionBuckets'],
  288. })
  289. if (!distributionBucket) {
  290. inconsistentState(`Distribution bucket by id ${distributionBucketId(bucketId)} not found!`)
  291. }
  292. // Remove relations
  293. await Promise.all(
  294. (distributionBucket.bags || []).map((bag) => {
  295. bag.distributionBuckets = (bag.distributionBuckets || []).filter(
  296. (bucket) => bucket.id !== distributionBucketId(bucketId)
  297. )
  298. return store.save<StorageBag>(bag)
  299. })
  300. )
  301. await store.remove<DistributionBucket>(distributionBucket)
  302. }
  303. export async function storage_DistributionBucketsUpdatedForBag({
  304. event,
  305. store,
  306. }: EventContext & StoreContext): Promise<void> {
  307. const [
  308. bagId,
  309. familyId,
  310. addedBucketsIndices,
  311. removedBucketsIndices,
  312. ] = new Storage.DistributionBucketsUpdatedForBagEvent(event).params
  313. // Get or create bag
  314. const storageBag = await getBag(store, bagId, ['distributionBuckets'])
  315. const removedBucketsIds = Array.from(removedBucketsIndices).map((bucketIndex) =>
  316. distributionBucketIdByFamilyAndIndex(familyId, bucketIndex)
  317. )
  318. const addedBucketsIds = Array.from(addedBucketsIndices).map((bucketIndex) =>
  319. distributionBucketIdByFamilyAndIndex(familyId, bucketIndex)
  320. )
  321. storageBag.distributionBuckets = (storageBag.distributionBuckets || [])
  322. .filter((bucket) => !removedBucketsIds.includes(bucket.id))
  323. .concat(addedBucketsIds.map((id) => new DistributionBucket({ id })))
  324. await store.save<StorageBag>(storageBag)
  325. }
  326. export async function storage_DistributionBucketModeUpdated({
  327. event,
  328. store,
  329. }: EventContext & StoreContext): Promise<void> {
  330. const [bucketId, distributing] = new Storage.DistributionBucketModeUpdatedEvent(event).params
  331. const bucket = await getById(store, DistributionBucket, distributionBucketId(bucketId))
  332. bucket.distributing = distributing.valueOf()
  333. await store.save<DistributionBucket>(bucket)
  334. }
  335. export async function storage_DistributionBucketOperatorInvited({
  336. event,
  337. store,
  338. }: EventContext & StoreContext): Promise<void> {
  339. const [bucketId, workerId] = new Storage.DistributionBucketOperatorInvitedEvent(event).params
  340. const bucket = await getById(store, DistributionBucket, distributionBucketId(bucketId))
  341. const invitedOperator = new DistributionBucketOperator({
  342. id: distributionOperatorId(bucketId, workerId),
  343. distributionBucket: bucket,
  344. status: DistributionBucketOperatorStatus.INVITED,
  345. workerId: workerId.toNumber(),
  346. })
  347. await store.save<DistributionBucketOperator>(invitedOperator)
  348. }
  349. export async function storage_DistributionBucketInvitationCancelled({
  350. event,
  351. store,
  352. }: EventContext & StoreContext): Promise<void> {
  353. const [bucketId, workerId] = new Storage.DistributionBucketOperatorInvitedEvent(event).params
  354. const invitedOperator = await getById(store, DistributionBucketOperator, distributionOperatorId(bucketId, workerId))
  355. await store.remove<DistributionBucketOperator>(invitedOperator)
  356. }
  357. export async function storage_DistributionBucketInvitationAccepted({
  358. event,
  359. store,
  360. }: EventContext & StoreContext): Promise<void> {
  361. const [workerId, bucketId] = new Storage.DistributionBucketInvitationAcceptedEvent(event).params
  362. const invitedOperator = await getById(store, DistributionBucketOperator, distributionOperatorId(bucketId, workerId))
  363. invitedOperator.status = DistributionBucketOperatorStatus.ACTIVE
  364. await store.save<DistributionBucketOperator>(invitedOperator)
  365. }
  366. export async function storage_DistributionBucketMetadataSet({
  367. event,
  368. store,
  369. }: EventContext & StoreContext): Promise<void> {
  370. const [workerId, bucketId, metadataBytes] = new Storage.DistributionBucketMetadataSetEvent(event).params
  371. const operator = await getDistributionBucketOperatorWithMetadata(store, distributionOperatorId(bucketId, workerId))
  372. operator.metadata = await processDistributionOperatorMetadata(store, operator.metadata, metadataBytes)
  373. await store.save<DistributionBucketOperator>(operator)
  374. }
  375. export async function storage_DistributionBucketOperatorRemoved({
  376. event,
  377. store,
  378. }: EventContext & StoreContext): Promise<void> {
  379. const [bucketId, workerId] = new Storage.DistributionBucketOperatorRemovedEvent(event).params
  380. // TODO: Cascade remove on db level (would require changes in Hydra / comitting autogenerated files)
  381. const operator = await getDistributionBucketOperatorWithMetadata(store, distributionOperatorId(bucketId, workerId))
  382. await store.remove<DistributionBucketOperator>(operator)
  383. if (operator.metadata) {
  384. await store.remove<DistributionBucketOperatorMetadata>(operator.metadata)
  385. if (operator.metadata.nodeLocation) {
  386. await store.remove<NodeLocationMetadata>(operator.metadata.nodeLocation)
  387. if (operator.metadata.nodeLocation.coordinates) {
  388. await store.remove<GeoCoordinates>(operator.metadata.nodeLocation.coordinates)
  389. }
  390. }
  391. }
  392. }
  393. // STORAGE SYSTEM GLOBAL PARAMS
  394. export async function storage_UpdateBlacklist({ event, store }: EventContext & StoreContext): Promise<void> {
  395. const [removedContentIds, addedContentIds] = new Storage.UpdateBlacklistEvent(event).params
  396. const storageSystem = await getStorageSystem(store)
  397. storageSystem.blacklist = storageSystem.blacklist
  398. .filter((cid) => !Array.from(removedContentIds).some((id) => id.eq(cid)))
  399. .concat(Array.from(addedContentIds).map((id) => id.toString()))
  400. await store.save<StorageSystemParameters>(storageSystem)
  401. }
  402. export async function storage_DistributionBucketsPerBagLimitUpdated({
  403. event,
  404. store,
  405. }: EventContext & StoreContext): Promise<void> {
  406. const [newLimit] = new Storage.DistributionBucketsPerBagLimitUpdatedEvent(event).params
  407. const storageSystem = await getStorageSystem(store)
  408. storageSystem.distributionBucketsPerBagLimit = newLimit.toNumber()
  409. await store.save<StorageSystemParameters>(storageSystem)
  410. }
  411. export async function storage_StorageBucketsPerBagLimitUpdated({
  412. event,
  413. store,
  414. }: EventContext & StoreContext): Promise<void> {
  415. const [newLimit] = new Storage.StorageBucketsPerBagLimitUpdatedEvent(event).params
  416. const storageSystem = await getStorageSystem(store)
  417. storageSystem.storageBucketsPerBagLimit = newLimit.toNumber()
  418. await store.save<StorageSystemParameters>(storageSystem)
  419. }
  420. export async function storage_StorageBucketsVoucherMaxLimitsUpdated({
  421. event,
  422. store,
  423. }: EventContext & StoreContext): Promise<void> {
  424. const [sizeLimit, countLimit] = new Storage.StorageBucketsVoucherMaxLimitsUpdatedEvent(event).params
  425. const storageSystem = await getStorageSystem(store)
  426. storageSystem.storageBucketMaxObjectsSizeLimit = sizeLimit
  427. storageSystem.storageBucketMaxObjectsCountLimit = countLimit
  428. await store.save<StorageSystemParameters>(storageSystem)
  429. }
  430. export async function storage_UploadingBlockStatusUpdated({
  431. event,
  432. store,
  433. }: EventContext & StoreContext): Promise<void> {
  434. const [isBlocked] = new Storage.UploadingBlockStatusUpdatedEvent(event).params
  435. const storageSystem = await getStorageSystem(store)
  436. storageSystem.uploadingBlocked = isBlocked.isTrue
  437. await store.save<StorageSystemParameters>(storageSystem)
  438. }
  439. export async function storage_DataObjectPerMegabyteFeeUpdated({
  440. event,
  441. store,
  442. }: EventContext & StoreContext): Promise<void> {
  443. const [newFee] = new Storage.DataObjectPerMegabyteFeeUpdatedEvent(event).params
  444. const storageSystem = await getStorageSystem(store)
  445. storageSystem.dataObjectFeePerMb = newFee
  446. await store.save<StorageSystemParameters>(storageSystem)
  447. }