From 1df8aa59812b48e120a785bd0f2e76badbbac9ae Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Sun, 21 Apr 2019 20:47:32 +0200 Subject: [PATCH] API: Modularize data source loaders --- src/api/data-sources/lsblk.js | 52 ++++++++++ src/api/data-sources/lvm/physical-volumes.js | 25 +++++ src/api/data-sources/smartctl/attributes.js | 12 +++ src/api/data-sources/smartctl/info.js | 12 +++ src/api/data-sources/smartctl/scan.js | 25 +++++ src/api/loaders.js | 103 +++---------------- 6 files changed, 139 insertions(+), 90 deletions(-) create mode 100644 src/api/data-sources/lsblk.js create mode 100644 src/api/data-sources/lvm/physical-volumes.js create mode 100644 src/api/data-sources/smartctl/attributes.js create mode 100644 src/api/data-sources/smartctl/info.js create mode 100644 src/api/data-sources/smartctl/scan.js diff --git a/src/api/data-sources/lsblk.js b/src/api/data-sources/lsblk.js new file mode 100644 index 0000000..54a3e10 --- /dev/null +++ b/src/api/data-sources/lsblk.js @@ -0,0 +1,52 @@ +"use strict"; + +const Promise = require("bluebird"); +const memoizee = require("memoizee"); + +const lsblk = require("../../wrappers/lsblk"); +const All = require("../../graphql/symbols/all"); + +function linearizeDevices(devices) { + let linearizedDevices = []; + + function add(list) { + for (let device of list) { + linearizedDevices.push(device); + + if (device.children != null) { + add(device.children); + } + } + } + + add(devices); + + return linearizedDevices; +} + +module.exports = function () { + let lsblkOnce = memoizee(() => { + return Promise.try(() => { + return lsblk(); + }).then((devices) => { + return { + tree: devices, + list: linearizeDevices(devices) + }; + }); + }); + + return function (names) { + return Promise.try(() => { + return lsblkOnce(); + }).then(({tree, list}) => { + return names.map((name) => { + if (name === All) { + return tree; + } else { + return list.find((device) => device.name === name); + } + }); + }); + }; +}; \ No newline at end of file diff --git a/src/api/data-sources/lvm/physical-volumes.js b/src/api/data-sources/lvm/physical-volumes.js new file mode 100644 index 0000000..eaf33a0 --- /dev/null +++ b/src/api/data-sources/lvm/physical-volumes.js @@ -0,0 +1,25 @@ +"use strict"; + +const Promise = require("bluebird"); +const memoizee = require("memoizee"); + +const lvm = require("../../../wrappers/lvm"); +const All = require("../../../graphql/symbols/all"); + +module.exports = function () { + let getPhysicalVolumesOnce = memoizee(lvm.getPhysicalVolumes); + + return function (paths) { + return Promise.try(() => { + return getPhysicalVolumesOnce(); + }).then((volumes) => { + return paths.map((path) => { + if (path === All) { + return volumes; + } else { + return volumes.find((device) => device.path === path); + } + }); + }); + }; +}; \ No newline at end of file diff --git a/src/api/data-sources/smartctl/attributes.js b/src/api/data-sources/smartctl/attributes.js new file mode 100644 index 0000000..f91d9b8 --- /dev/null +++ b/src/api/data-sources/smartctl/attributes.js @@ -0,0 +1,12 @@ +"use strict"; + +const Promise = require("bluebird"); +const smartctl = require("../../../wrappers/smartctl"); + +module.exports = function () { + return function (paths) { + return Promise.map(paths, (path) => { + return smartctl.attributes({ devicePath: path }); + }); + }; +}; \ No newline at end of file diff --git a/src/api/data-sources/smartctl/info.js b/src/api/data-sources/smartctl/info.js new file mode 100644 index 0000000..62090b0 --- /dev/null +++ b/src/api/data-sources/smartctl/info.js @@ -0,0 +1,12 @@ +"use strict"; + +const Promise = require("bluebird"); +const smartctl = require("../../../wrappers/smartctl"); + +module.exports = function () { + return function (paths) { + return Promise.map(paths, (path) => { + return smartctl.info({ devicePath: path }); + }); + }; +}; \ No newline at end of file diff --git a/src/api/data-sources/smartctl/scan.js b/src/api/data-sources/smartctl/scan.js new file mode 100644 index 0000000..81310f3 --- /dev/null +++ b/src/api/data-sources/smartctl/scan.js @@ -0,0 +1,25 @@ +"use strict"; + +const Promise = require("bluebird"); +const memoizee = require("memoizee"); + +const smartctl = require("../../../wrappers/smartctl"); +const All = require("../../../graphql/symbols/all"); + +module.exports = function () { + let scanOnce = memoizee(smartctl.scan); + + return function (paths) { + return Promise.try(() => { + return scanOnce(); + }).then((devices) => { + return paths.map((path) => { + if (path === All) { + return devices; + } else { + return devices.find((device) => device.path === path); + } + }); + }); + }; +}; \ No newline at end of file diff --git a/src/api/loaders.js b/src/api/loaders.js index 8015e53..346de45 100644 --- a/src/api/loaders.js +++ b/src/api/loaders.js @@ -1,98 +1,21 @@ "use strict"; -const Promise = require("bluebird"); -const memoizee = require("memoizee"); const DataLoader = require("dataloader"); +const mapObj = require("map-obj"); -const lvm = require("../wrappers/lvm"); -const smartctl = require("../wrappers/smartctl"); -const lsblk = require("../wrappers/lsblk"); -const findmnt = require("../wrappers/findmnt"); -const All = require("../graphql/symbols/all"); - -function linearizeDevices(devices) { - let linearizedDevices = []; - - function add(list) { - for (let device of list) { - linearizedDevices.push(device); - - if (device.children != null) { - add(device.children); - } - } - } - - add(devices); - - return linearizedDevices; -} +let dataSourceFactories = { + lsblk: require("./data-sources/lsblk"), + smartctlInfo: require("./data-sources/smartctl/info"), + smartctlScan: require("./data-sources/smartctl/scan"), + smartctlAttributes: require("./data-sources/smartctl/attributes"), + lvmPhysicalVolumes: require("./data-sources/lvm/physical-volumes"), +}; module.exports = function createLoaders() { - /* The below is to ensure that commands that produce a full list of all possible items, only ever get called and processed *once* per query, no matter what data is requested. */ - let smartctlScanOnce = memoizee(smartctl.scan); - let lvmGetPhysicalVolumesOnce = memoizee(lvm.getPhysicalVolumes); - - let lsblkOnce = memoizee(() => { - return Promise.try(() => { - return lsblk(); - }).then((devices) => { - return { - tree: devices, - list: linearizeDevices(devices) - }; - }); + return mapObj(dataSourceFactories, (name, factory) => { + return [ + name, + new DataLoader(factory()) + ]; }); - - return { - lsblk: new DataLoader((names) => { - return Promise.try(() => { - return lsblkOnce(); - }).then(({tree, list}) => { - return names.map((name) => { - if (name === All) { - return tree; - } else { - return list.find((device) => device.name === name); - } - }); - }); - }), - smartctlScan: new DataLoader((paths) => { - return Promise.try(() => { - return smartctlScanOnce(); - }).then((devices) => { - return paths.map((path) => { - if (path === All) { - return devices; - } else { - return devices.find((device) => device.path === path); - } - }); - }); - }), - smartctlInfo: new DataLoader((paths) => { - return Promise.map(paths, (path) => { - return smartctl.info({ devicePath: path }); - }); - }), - smartctlAttributes: new DataLoader((paths) => { - return Promise.map(paths, (path) => { - return smartctl.attributes({ devicePath: path }); - }); - }), - lvmPhysicalVolumes: new DataLoader((paths) => { - return Promise.try(() => { - return lvmGetPhysicalVolumesOnce(); - }).then((volumes) => { - return paths.map((path) => { - if (path === All) { - return volumes; - } else { - return volumes.find((device) => device.path === path); - } - }); - }); - }), - }; }; \ No newline at end of file