|
39 | 39 |
|
40 | 40 | <script> |
41 | 41 | import get from 'lodash/get'; |
| 42 | + import differenceInSeconds from 'date-fns/difference_in_seconds'; |
42 | 43 |
|
43 | 44 | export default { |
44 | 45 | name: 'server-box', |
45 | 46 | props: { |
46 | 47 | server: { type: Object, required: true }, |
47 | 48 | }, |
48 | 49 |
|
| 50 | + dataGetTimeout: null, |
| 51 | +
|
49 | 52 | data: function () { |
50 | 53 | return { |
| 54 | + backgroundedAt: new Date(), |
| 55 | + documentVisible: true, |
51 | 56 | resources: undefined, |
52 | 57 | cpu: 0, |
53 | 58 | memory: 0, |
54 | 59 | status: '', |
55 | 60 | }; |
56 | 61 | }, |
57 | 62 |
|
| 63 | + watch: { |
| 64 | + /** |
| 65 | + * Watch the documentVisible item and perform actions when it is changed. If it becomes |
| 66 | + * true, we want to check how long ago the last poll was, if it was more than 30 seconds |
| 67 | + * we want to immediately trigger the resourceUse api call, otherwise we just want to restart |
| 68 | + * the time. |
| 69 | + * |
| 70 | + * If it is now false, we want to clear the timer that checks resource use, since we know |
| 71 | + * we won't be doing anything with them anyways. Might as well avoid extraneous resource |
| 72 | + * usage by the browser. |
| 73 | + */ |
| 74 | + documentVisible: function (value) { |
| 75 | + if (!value) { |
| 76 | + window.clearTimeout(this.$options.dataGetTimeout); |
| 77 | + return; |
| 78 | + } |
| 79 | +
|
| 80 | + if (differenceInSeconds(new Date(), this.backgroundedAt) >= 30) { |
| 81 | + this.getResourceUse(); |
| 82 | + } |
| 83 | +
|
| 84 | + this.$options.dataGetTimeout = window.setInterval(() => { |
| 85 | + this.getResourceUse(); |
| 86 | + }, 10000); |
| 87 | + }, |
| 88 | + }, |
| 89 | +
|
| 90 | + /** |
| 91 | + * Grab the initial resource usage for this specific server instance and add a listener |
| 92 | + * to monitor when this window is no longer visible. We don't want to needlessly poll the |
| 93 | + * API when we aren't looking at the page. |
| 94 | + */ |
58 | 95 | created: function () { |
59 | | - window.events.$on(`server:${this.server.uuid}::resources`, data => { |
60 | | - this.resources = data; |
61 | | - this.status = this.getServerStatus(); |
62 | | -
|
63 | | - this.memory = Number(get(data, 'memory.current', 0)).toFixed(0); |
64 | | - this.cpu = this._calculateCpu( |
65 | | - Number(get(data, 'cpu.current', 0)), |
66 | | - Number(this.server.limits.cpu) |
67 | | - ); |
68 | | - }); |
| 96 | + this.getResourceUse(); |
| 97 | + document.addEventListener('visibilitychange', this._visibilityChange.bind(this)); |
| 98 | + }, |
| 99 | +
|
| 100 | + /** |
| 101 | + * Poll the API for changes every 10 seconds when the component is mounted. |
| 102 | + */ |
| 103 | + mounted: function () { |
| 104 | + this.$options.dataGetTimeout = window.setInterval(() => { |
| 105 | + this.getResourceUse(); |
| 106 | + }, 10000); |
| 107 | + }, |
| 108 | +
|
| 109 | + /** |
| 110 | + * Clear the timer and event listeners when we destroy the component. |
| 111 | + */ |
| 112 | + beforeDestroy: function () { |
| 113 | + window.clearInterval(this.$options.dataGetTimeout); |
| 114 | + document.removeEventListener('visibilitychange', this._visibilityChange.bind(this), false); |
69 | 115 | }, |
70 | 116 |
|
71 | 117 | methods: { |
| 118 | + /** |
| 119 | + * Query the resource API to determine what this server's state and resource usage is. |
| 120 | + */ |
| 121 | + getResourceUse: function () { |
| 122 | + window.axios.get(this.route('api.client.servers.resources', { server: this.server.identifier })) |
| 123 | + .then(response => { |
| 124 | + if (!(response.data instanceof Object)) { |
| 125 | + throw new Error('Received an invalid response object back from status endpoint.'); |
| 126 | + } |
| 127 | +
|
| 128 | +
|
| 129 | + this.resources = response.data.attributes; |
| 130 | + this.status = this.getServerStatus(); |
| 131 | +
|
| 132 | + this.memory = Number(get(this.resources, 'memory.current', 0)).toFixed(0); |
| 133 | + this.cpu = this._calculateCpu( |
| 134 | + Number(get(this.resources, 'cpu.current', 0)), |
| 135 | + Number(this.server.limits.cpu) |
| 136 | + ); |
| 137 | + }) |
| 138 | + .catch(err => { |
| 139 | + console.error({ err }); |
| 140 | + }); |
| 141 | + }, |
| 142 | +
|
72 | 143 | /** |
73 | 144 | * Set the CSS to use for displaying the server's current status. |
74 | 145 | */ |
|
107 | 178 | } |
108 | 179 |
|
109 | 180 | return parseFloat((current / max * 100).toFixed(1)); |
110 | | - } |
| 181 | + }, |
| 182 | +
|
| 183 | + /** |
| 184 | + * Handle document visibility changes. |
| 185 | + * |
| 186 | + * @private |
| 187 | + */ |
| 188 | + _visibilityChange: function () { |
| 189 | + this.documentVisible = document.visibilityState === 'visible'; |
| 190 | +
|
| 191 | + if (!this.documentVisible) { |
| 192 | + this.backgroundedAt = new Date(); |
| 193 | + } |
| 194 | + }, |
111 | 195 | } |
112 | 196 | }; |
113 | 197 | </script> |
0 commit comments