diff --git a/dashboard/src/models/ServicesModel.js b/dashboard/src/models/ServicesModel.js index 96c290a93..ad01848e2 100644 --- a/dashboard/src/models/ServicesModel.js +++ b/dashboard/src/models/ServicesModel.js @@ -33,6 +33,17 @@ function create(origin, accessToken) { error = e; } + if (error || result.status !== 202) return [error || result]; + return [null]; + }, + async update(id, memoryLimit, recoveryMode) { + let error, result; + try { + result = await fetcher.post(`${origin}/api/v1/services/${id}`, {memoryLimit, recoveryMode}, { access_token: accessToken }); + } catch (e) { + error = e; + } + if (error || result.status !== 202) return [error || result]; return [null]; }, diff --git a/dashboard/src/views/ServicesView.vue b/dashboard/src/views/ServicesView.vue index 58b79ee9d..521293b53 100644 --- a/dashboard/src/views/ServicesView.vue +++ b/dashboard/src/views/ServicesView.vue @@ -7,15 +7,17 @@ const i18n = useI18n(); const t = i18n.t; import { computed, reactive, onMounted, ref, useTemplateRef } from 'vue'; -import { Button, TableView, ProgressBar, ButtonGroup, Dialog } from 'pankow'; +import { Button, TableView, ProgressBar, ButtonGroup, FormGroup, Checkbox, Dialog } from 'pankow'; import { prettyBinarySize } from 'pankow/utils'; import { each } from 'async'; import Section from '../components/Section.vue'; import ServicesModel from '../models/ServicesModel.js'; +import SystemModel from '../models/SystemModel.js'; import AppsModel from '../models/AppsModel.js'; const appsModel = AppsModel.create(API_ORIGIN, localStorage.token); const servicesModel = ServicesModel.create(API_ORIGIN, localStorage.token); +const systemModel = SystemModel.create(API_ORIGIN, localStorage.token); const columns = { status: {}, @@ -94,20 +96,57 @@ const dialog = useTemplateRef('dialog'); const editService = ref({}); const editError = ref(''); const editBusy = ref(false); +const editMemoryLimit = ref(0); +const editMemoryTicks = ref([]); +const editRecoveryMode = ref(false); + +let availableSystemMemory = 4 * 1024 * 1024 * 1024; async function onEdit(service) { + console.log(service) editService.value = service; + editMemoryLimit.value = service.config.memoryLimit; + editRecoveryMode.value = service.config.recoveryMode; + + editMemoryTicks.value = []; + // we max system memory and current service memory for the case where the user configured the service on another server with more resources + const nearest256m = Math.ceil(Math.max(availableSystemMemory, editService.value.config.memoryLimit) / (256*1024*1024)) * 256 * 1024 * 1024; + const startTick = editService.value.defaultMemoryLimit; + + // code below ensure we atleast have 2 ticks to keep the slider usable + editMemoryTicks.value.push(startTick); // start tick + for (let i = startTick * 2; i < nearest256m; i *= 2) editMemoryTicks.value.push(i); + editMemoryTicks.value.push(nearest256m); // end tick + dialog.value.open(); } +function onResetToDefaults() { + editMemoryLimit.value = editService.value.defaultMemoryLimit; +} + async function onEditConfirm() { editBusy.value = true; + + const [error] = await servicesModel.update(editService.value.id, parseInt(editMemoryLimit.value), editRecoveryMode.value); + if (error) { + console.error(error); + editError.value = error.body ? error.body.message : 'Internal Error'; + editBusy.value = false; + return; + } + + setTimeout(() => refresh(editService.value.id), 2000); editBusy.value = false; dialog.value.close(); } onMounted(async () => { await refreshAll(); + + const [error, result] = await systemModel.memory(); + if (error) return console.error(error); + availableSystemMemory = result.memory; }); @@ -123,6 +162,19 @@ onMounted(async () => { @confirm="onEditConfirm()" >
{{ editError }}
+ +