Gum-Joe / 2Keys

A easy to setup second keyboard, designed for everyone.
GNU General Public License v3.0
11 stars 4 forks source link

Execute on a different thread, because the server ... #130

Closed github-actions[bot] closed 4 years ago

github-actions[bot] commented 4 years ago

Execute on a different thread, because the server hangs and fails any in progress runs if it is still waiting for this

https://github.com/Gum-Joe/2Keys/blob/b8516e5cb264299d2ab5df25766a29dd6c8381bf/packages/@twokeys/server/src/routes/api.ts#L229

    });

    /**
     * Trigger a hotkey
     * 
     * Provide these property:
     * ```json
     * {
     *  "hotkey": "^A" // hotkey code to find in keyboard
     *  "event": "up" | "down" | "hold" // OPTIONAL event type
     * }
     * ```
     */
    router.post("/post/:detector/:keyboard/trigger", (req, res, next) => {
        const { detector: detectorName, keyboard: keyboardName } = req.params;
        logger.info(`Got trigger for detector ${detectorName}, keyboard ${keyboardName}`);

        logger.info("Validating POST body");
        if (!hasOwnProperty(req, "body") || typeof req.body !== "object" || typeof req.body.hotkey !== "string") {
            logger.err("Invalid POST body! Properties were missing!");
            res.statusCode = 422;
            res.json({
                message: "Invalid POST body! Properties were missing!",
            });
            return;
        }

        const hotkey = req.body.hotkey as string;
        const eventType: keyof HotkeyTypeKeypressValue = req.body.event || "down";
        if (eventType !== "up" && eventType !== "down" && eventType !== "hold") {
            logger.err("Bad event field given!");
            res.statusCode = 422;
            res.json({
                message: "Bad event field given!",
            });
            return;
        }

        // 1: Grab config
        logger.debug(`Grabbing config for detector ${detectorName}, keyboard ${keyboardName}...`);
        if (!detectors.has(detectorName)) {
            logger.err(`Detector ${detectorName} not found!`);
            res.statusCode = 404;
            res.json({
                message: "Detector Not Found"
            });
            return;
        }
        const detector = detectors.get(detectorName) as DetectorConfig;
        if (hasOwnProperty(detector.keyboards, keyboardName)) {
            logger.debug(`Keybaord ${keyboardName} found`)
            const keyboard = detector.keyboards[keyboardName];

            if (!hasOwnProperty(keyboard.hotkeys, hotkey)) {
                logger.err(`Hotkey ${hotkey} not found!`);
                res.statusCode = 404;
                res.json({
                    message: "Hotkey Not Found"
                });
                return;
            }

            // eslint-disable-next-line no-inner-declarations
            function isMultiHotkey(hotkey: Hotkey): hotkey is HotkeyTypeKeypressValue {
                if (hasOwnProperty(hotkey, "up") || hasOwnProperty(hotkey, "down") || hasOwnProperty(hotkey, "hold")) {
                    return true;
                } else {
                    return false;
                }
            }

            // eslint-disable-next-line no-inner-declarations
            async function executeHotKey(hotkey: HotkeyTypeSingle, hotkeyCode: string, keyboard: Keyboard): Promise<void> {
                logger.info(`Executing hotkey ${hotkey}...`);
                const executorToCall = hotkey.executor || keyboard.executors.default;
                const configForExecutor: ExecutorExecConfig<{ [key: string]: any }> = {
                    hotkey: {
                        ...(keyboard.executors[executorToCall] || {}), // Falback in case no config
                        ...hotkey,
                    },
                    hotkeyCode,
                    executorDefaultConfig: (keyboard.executors[executorToCall] || {}),
                    keyboard,
                };
                logger.debug(`Providing ${JSON.stringify(configForExecutor)} to executor`);
                if (!hasOwnProperty(executors, executorToCall)) {
                    logger.err(`Executor ${executorToCall} not found installed!`);
                    throw new CodedError("Executor to use not found!");
                }
                await executors[executorToCall].call(executors[executorToCall].execute, configForExecutor);
                return;
            }

            const theHotkey = keyboard.hotkeys[hotkey];
            if (isMultiHotkey(theHotkey)) {
                if (typeof theHotkey[eventType] !== "object") {
                    return next(new CodedError(`Hotkey event ${eventType} not found!`, ERR_BAD_EVENT_TYPE));
                } else {
                    executeHotKey(theHotkey[eventType] as HotkeyTypeSingle, hotkey, keyboard)
                        .catch(next)
                        .then(() => {
                            logger.info("Execution done.");
                        });
                    // Send back to prevent timeout from long hotkeys
                    res.statusCode = 200;
                    res.json({
                        message: "Run triggered",
                    });
                    res.end();
                    return;
                }
            } else {
                // TODO: Execute on a different thread, because the server hangs and fails any in progress runs if it is still waiting for this
                executeHotKey(theHotkey, hotkey, keyboard)
                    .catch(next)
                    .then(() => {
                        logger.info("Execution done.");
                    });
                // Send back to prevent timeout from long hotkeys
                res.statusCode = 200;
                res.json({
                    message: "Run triggered",
                });
                res.end();
                return;
            }

        } else {
            logger.err(`Keyboard ${keyboardName} not found!`);
            res.statusCode = 404;
            res.json({
                message: "Keyboard Not Found"
            });
            return;
        }

    });

    /**
     * Trigger a hotkey
     * Info to send:
     * - keyboard: The keyboard name that has been pressed
     * - hotkey: set of keys that have been pressed
     * @deprecated
     */
    router.post("/post/depreacted/trigger", async (req, res, next) => {
        /**
         * 1: Get hotkey function from config
         * 2: Execute C++ bindings with #Include <root of keyboard>; function()
ndex b453158..be47bc1 100644
++ b/packages/@twokeys/server/src/routes/loadExecutors.ts

382473dd7492d4837b7bdab89203831cf8c7495a

github-actions[bot] commented 4 years ago

Closed in c9c607e3d2a9df04e8f3f33e46e66956fd5c5e17