{ "version": 3, "sources": ["../ui/app/mn.buckets.service.js"], "sourcesContent": ["/*\nCopyright 2020-Present Couchbase, Inc.\n\nUse of this software is governed by the Business Source License included in\nthe file licenses/BSL-Couchbase.txt. As of the Change Date specified in that\nfile, in accordance with the Business Source License, use of this software will\nbe governed by the Apache License, Version 2.0, included in the file\nlicenses/APL2.txt.\n*/\nimport {Injectable} from '@angular/core';\nimport {NgbModal} from '@ng-bootstrap/ng-bootstrap';\n\nimport {HttpClient, HttpParams} from '@angular/common/http';\nimport {pluck, switchMap, concatMap, shareReplay,\n distinctUntilChanged, map, withLatestFrom} from 'rxjs/operators';\nimport {BehaviorSubject, timer, combineLatest} from 'rxjs';\nimport {filter, anyPass, allPass, propEq} from 'ramda';\n\nimport {singletonGuard} from './mn.core.js'\nimport {MnAdminService} from './mn.admin.service.js';\nimport {MnPermissions} from './ajs.upgraded.providers.js';\nimport {MnHttpRequest} from './mn.http.request.js';\nimport {MnHelperService} from './mn.helper.service.js';\nimport {MnSettingsAutoCompactionService} from './mn.settings.auto.compaction.service.js';\n\nexport {MnBucketsService};\n\nclass MnBucketsService {\n static get annotations() { return [\n new Injectable()\n ]}\n\n static get parameters() { return [\n HttpClient,\n MnAdminService,\n MnHelperService,\n MnSettingsAutoCompactionService,\n MnPermissions,\n NgbModal\n ]}\n\n constructor(http, mnAdminService, mnHelperService, mnSettingsAutoCompactionService, mnPermissions, modalService) {\n singletonGuard(MnBucketsService);\n\n this.stream = {};\n this.http = http;\n this.modalService = modalService;\n this.mnHelperService = mnHelperService;\n this.mnAdminService = mnAdminService;\n this.mnSettingsAutoCompactionService = mnSettingsAutoCompactionService;\n\n this.stream.bucketsUri = mnAdminService.stream.getPoolsDefault\n .pipe(pluck(\"buckets\", \"uri\"),\n distinctUntilChanged());\n\n this.stream.getBuckets = this.stream.bucketsUri\n .pipe(switchMap(this.get.bind(this)),\n shareReplay({refCount: true, bufferSize: 1}));\n\n this.stream.updateBucketsPoller = new BehaviorSubject();\n\n this.stream.getBucketsByName = this.stream.getBuckets\n .pipe(map(buckets =>\n buckets.reduce((acc, bucket) => {\n acc[bucket.name] = bucket;\n return acc;\n }, {})),\n shareReplay({refCount: true, bufferSize: 1}));\n\n this.stream.bucketsMembaseCouchstore = this.stream.getBuckets\n .pipe(map(filter(allPass([propEq('bucketType', 'membase'),\n propEq('storageBackend', 'couchstore')]))),\n shareReplay({refCount: true, bufferSize: 1}));\n\n this.stream.bucketsMembaseEphemeral = this.stream.getBuckets\n .pipe(map(filter(anyPass([propEq('bucketType', 'membase'),\n propEq('bucketType', 'ephemeral')]))),\n shareReplay({refCount: true, bufferSize: 1}));\n\n this.stream.getBucketsPool =\n combineLatest(this.stream.bucketsUri,\n timer(0, 4000),\n this.stream.updateBucketsPoller)\n .pipe(map(([url,]) => url),\n concatMap(this.get.bind(this)),\n shareReplay({refCount: true, bufferSize: 1}));\n\n this.stream.defaultAutoCompactionData = mnSettingsAutoCompactionService.stream.settingsSource;\n\n this.stream.deleteBucket =\n new MnHttpRequest(this.deleteBucket.bind(this))\n .addSuccess()\n .addError();\n\n this.stream.flushBucket =\n new MnHttpRequest(this.flushBucket.bind(this))\n .addSuccess()\n .addError();\n }\n\n isNewBucketAllowed([permissions, maxBucketsCountReached, isRebalancing]) {\n return permissions.cluster.buckets.create && !isRebalancing && !maxBucketsCountReached;\n }\n\n getNodesCountByStatus(nodes) {\n let nodesByStatuses = {};\n\n nodes.forEach(node => {\n let status = this.getMessage(node.status, node.clusterMembership);\n\n if (status) {\n nodesByStatuses[status] = (nodesByStatuses[status] || 0) + 1;\n }\n });\n\n return nodesByStatuses;\n }\n\n getMessage(status, clusterMembership) {\n let rvStatus = clusterMembership === 'inactiveFailed' ? 'failed over, ' : '';\n\n switch (status) {\n case 'unhealthy':\n return rvStatus + 'not responding';\n case 'warmup':\n return rvStatus + 'pending';\n default:\n return rvStatus;\n }\n }\n\n getNodesCountByStatusMessage(statusCount) {\n return Object.keys(statusCount).map(status => {\n return statusCount[status] + ' node' + (statusCount[status] !== 1 ? \"s\" : \"\") + ' ' + status;\n });\n }\n\n getWarmUpProgress([tasks, bucket]) {\n if (!bucket || !tasks) {\n return false;\n }\n\n let task = tasks.find(task => task.bucket === bucket.name);\n if (task) {\n if (!(Number(task.stats.ep_warmup_estimated_key_count) ||\n Number(task.stats.ep_warmup_estimated_value_count))) {\n return 0;\n }\n\n let totalPercent = 0;\n switch (task.stats.ep_warmup_state) {\n case \"loading keys\":\n totalPercent += (Number(task.stats.ep_warmup_key_count) /\n Number(task.stats.ep_warmup_estimated_key_count) * 100);\n break;\n case \"loading data\":\n totalPercent += (Number(task.stats.ep_warmup_value_count) /\n Number(task.stats.ep_warmup_estimated_value_count) * 100);\n break;\n default:\n break;\n }\n\n return totalPercent / bucket.nodes.length;\n }\n\n return false;\n }\n\n getNodesStatusClass(nodes) {\n let statusClass = nodes.length ? 'healthy' : 'inactive';\n\n for (let i = 0; i < nodes.length; i++) {\n let node = nodes[i];\n if (node.status === 'unhealthy') {\n statusClass = 'unhealthy';\n break;\n }\n if (statusClass !== 'inactiveFailed' && node.status === 'warmup') {\n statusClass = 'warmup';\n }\n if (node.clusterMembership === 'inactiveFailed') {\n statusClass = 'inactiveFailed';\n }\n }\n\n return ('dynamic_' + statusClass);\n }\n\n getResidentRatio(bucket) {\n let items = bucket.basicStats.itemCount;\n let activeResident = bucket.basicStats.vbActiveNumNonResident;\n\n if (items === 0) {\n return 100;\n } else if (items < activeResident) {\n return 0;\n }\n\n return (items - activeResident) * 100 / items;\n }\n\n getRamConfigParams(bucket) {\n if (!bucket) {\n return;\n }\n\n let totals = bucket.basicStats.storageTotals.ram;\n return {\n total: totals.quotaTotalPerNode * bucket.nodes.length,\n thisAlloc: bucket.quota.ram,\n otherBuckets: totals.quotaUsedPerNode * bucket.nodes.length - bucket.quota.ram\n };\n }\n\n getDiskConfigParams(bucket) {\n if (!bucket) {\n return;\n }\n\n let totals = bucket.basicStats.storageTotals.hdd;\n return {\n total: totals.total,\n thisBucket: bucket.basicStats.diskUsed,\n otherBuckets: totals.usedByData - bucket.basicStats.diskUsed,\n otherData: totals.used - totals.usedByData\n };\n }\n\n getRamConfig(ramSummary) {\n if (!ramSummary) {\n return;\n }\n\n let config = {};\n config.topRight = {\n name: 'cluster quota',\n value: ramSummary.total\n };\n\n let available = ramSummary.total - ramSummary.otherBuckets - ramSummary.thisAlloc;\n config.items = [{\n name: 'other buckets',\n value: ramSummary.otherBuckets\n }, {\n name: 'this bucket',\n value: ramSummary.thisAlloc\n }, {\n name: 'available',\n value: available\n }];\n\n if (available < 0) {\n config.items[1].value = ramSummary.total - ramSummary.otherBuckets;\n config.items[2] = {\n name: 'overcommitted',\n value: ramSummary.otherBuckets + ramSummary.thisAlloc - ramSummary.total\n };\n config.topLeft = {\n name: 'total allocated',\n value: ramSummary.otherBuckets + ramSummary.thisAlloc\n };\n }\n\n return config;\n }\n\n getDiskConfig(diskSummary) {\n var config = {};\n\n let available = diskSummary.total - diskSummary.otherData - diskSummary.thisBucket - diskSummary.otherBuckets;\n config.topRight = {\n name: 'total cluster storage',\n value: diskSummary.total\n };\n config.items = [{\n name: 'other buckets',\n value: diskSummary.otherBuckets\n }, {\n name: 'this bucket',\n value: diskSummary.thisBucket\n }, {\n name: 'available',\n value: available\n }];\n\n return config;\n }\n\n getWarmUpTasks([tasks, bucket]) {\n return tasks.filter(task => {\n let isNeeded = task.bucket === bucket.name;\n if (isNeeded) {\n task.hostname = bucket.nodes.find(node => node.otpNode === task.node).hostname;\n }\n return isNeeded;\n });\n }\n\n prepareEjectionMethodText(bucket) {\n switch (bucket.bucketType) {\n case 'ephemeral':\n if (bucket.evictionPolicy === 'noEviction') {\n return 'No ejection';\n } else {\n return 'Eject data when RAM is full';\n }\n default:\n if (bucket.evictionPolicy === 'valueOnly') {\n return 'Value-Only';\n } else {\n return 'Full';\n }\n }\n }\n\n prepareStorageBackendText(bucket) {\n switch (bucket.storageBackend) {\n case 'couchstore':\n return 'CouchStore';\n case 'magma':\n return 'Magma';\n default:\n return '';\n }\n }\n\n prepareCompactionProgressText(compactionTask) {\n return compactionTask ? (compactionTask.progress + '% complete') : 'Not active';\n }\n\n getCompactionTask([compactionTasks, bucketName]) {\n return compactionTasks[bucketName] && compactionTasks[bucketName][0];\n }\n\n isCompactDisabled([startedCompactions, bucketControllers, compactionTask]) {\n return startedCompactions[bucketControllers.compactAll] || compactionTask;\n }\n\n isCancelCompactDisabled([startedCompactions, compactionTask]) {\n return compactionTask && startedCompactions[compactionTask.cancelURI];\n }\n\n showCompactBtn([compactionTask, bucketName, bucketType, permissions]) {\n return (!compactionTask || !compactionTask.cancelURI) &&\n bucketType === 'membase' &&\n permissions.cluster.tasks.read &&\n permissions.cluster.bucket[bucketName].compact;\n }\n\n showCancelCompactBtn([compactionTask, bucketName, permissions]) {\n return (compactionTask && compactionTask.cancelURI) &&\n permissions.cluster.tasks.read &&\n permissions.cluster.bucket[bucketName].compact;\n }\n\n showFlushBtn([controllers, bucketName, permissions]) {\n return controllers && controllers.flush &&\n permissions.cluster.bucket[bucketName].flush;\n }\n\n unpackData([autoCompactionSettings, reallyActiveKVNodes], storageTotals) {\n let ramQuota = 0;\n let ram = storageTotals.ram;\n if (ram) {\n ramQuota = Math.floor(\n (ram.quotaTotal - ram.quotaUsed) / reallyActiveKVNodes.length);\n }\n\n return {\n name: '',\n ramQuotaMB: this.mnHelperService.transformBytesToMB(ramQuota),\n bucketType: 'membase',\n replicaNumberEnabled: true,\n replicaNumber: 1,\n replicaIndex: 0,\n evictionPolicy: 'valueOnly',\n evictionPolicyEphemeral: 'noEviction',\n maxTTLEnabled: false,\n maxTTL: 0,\n compressionMode: 'passive',\n conflictResolutionType: 'seqno',\n flushEnabled: 0,\n threadsNumber: '3',\n purgeInterval: 3,\n durabilityMinLevel: 'none',\n storageBackend: 'couchstore',\n autoCompactionDefined: false,\n autoCompactionSettings\n };\n }\n\n getBucketFormData(defaultAutoCompaction, bucket) {\n let result = {\n name: bucket.name,\n ramQuotaMB: this.mnHelperService.transformBytesToMB(bucket.quota.rawRAM),\n bucketType: bucket.bucketType,\n replicaNumberEnabled: bucket.replicaNumber !== 0,\n replicaNumber: bucket.replicaNumber,\n replicaIndex: bucket.replicaIndex,\n evictionPolicy: bucket.evictionPolicy,\n evictionPolicyEphemeral: bucket.evictionPolicy,\n maxTTLEnabled: bucket.maxTTL !== 0,\n maxTTL: bucket.maxTTL,\n compressionMode: bucket.compressionMode,\n conflictResolutionType: bucket.conflictResolutionType,\n flushEnabled: (bucket.controllers && bucket.controllers.flush) ? 1 : 0,\n threadsNumber: bucket.threadsNumber + '',\n purgeInterval: bucket.purgeInterval,\n durabilityMinLevel: bucket.durabilityMinLevel,\n storageBackend: bucket.storageBackend,\n autoCompactionDefined: !!bucket.autoCompactionSettings,\n };\n\n let autoCompaction = this.mnSettingsAutoCompactionService.getSettingsSource(\n bucket.autoCompactionSettings ? bucket : {autoCompactionSettings: defaultAutoCompaction});\n autoCompaction.purgeInterval = bucket.autoCompactionSettings ?\n bucket.purgeInterval : defaultAutoCompaction.purgeInterval;\n result = Object.assign(result, {autoCompactionSettings: autoCompaction});\n\n return result;\n }\n\n createBucketFormData(bucket) {\n return this.stream.defaultAutoCompactionData\n .pipe(map(v => this.getBucketFormData(v, bucket)));\n }\n\n createInitialFormData(storageTotals) {\n return this.stream.defaultAutoCompactionData\n .pipe(withLatestFrom(this.mnAdminService.stream.reallyActiveKVNodes),\n map(v => this.unpackData(v, storageTotals)));\n }\n\n get(url) {\n return this.http.get(\n url,\n {params: new HttpParams().set('skipMap', true).set('basic_stats', true)}\n );\n }\n\n createPostBucketPipe(id) {\n this.stream.postBucket =\n new MnHttpRequest(this.postBucket.bind(this, false, id))\n .addSuccess()\n .addError();\n return this.stream.postBucket;\n }\n\n createPostValidationPipe(id) {\n this.stream.postBucketValidation =\n new MnHttpRequest(this.postBucket.bind(this, true, id))\n .addSuccess()\n .addError();\n return this.stream.postBucketValidation;\n }\n\n postBucket(justValidate, bucketId, payload) {\n let params = new HttpParams();\n if (justValidate) {\n params = params.set('just_validate', 1).set('ignore_warnings', 0);\n }\n\n let url = '/pools/default/buckets';\n if (bucketId) {\n url = url + '/' + payload.name;\n params = params.set('bucket_uuid', bucketId);\n }\n\n return this.http.post(url, payload, {params});\n }\n\n deleteBucket(bucket) {\n return this.http.delete(bucket.uri);\n }\n\n flushBucket(bucket) {\n return this.http.post(bucket.controllers.flush);\n }\n\n postCompact(postURL) {\n return this.http.post(postURL);\n }\n}\n"], "mappings": "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", "names": [] }