zoukankan      html  css  js  c++  java
  • plv8 require 模块试用

    plv8 是postgres 的一个比较强大的插件,社区有人基于babel,browserify 实现了一个方便的require 模块加载
    实际上官方也有介绍过了类似的基于数据库存储js,然后通过eval 动态加载代码,以下是一个简单的试用

    环境准备

    • docker-compose 文件
     
    version: '3.6'
    services:
      postgres:
        image: dalongrong/plv8:2.3.12
        ports:
        - "5432:5432"
        environment: 
        - "POSTGRES_PASSWORD=dalong"
      graphql-engine:
        image: hasura/graphql-engine:v1.0.0-beta.9
        ports:
        - "8080:8080"
        depends_on:
        - "postgres"
        environment:
          HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:dalong@postgres:5432/postgres
          HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
          HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
    • node-plv8 项目
      package.json
     
    {
      "name": "node-plv8",
      "version": "1.0.0",
      "main": "app.js",
      "bin": "app.js",
      "license": "MIT",
      "dependencies": {
        "cuid": "^2.1.6",
        "knex": "^0.20.1",
        "lodash": "^4.17.15",
        "pg": "^7.12.1",
        "plv8": "^2.1.4",
        "uuid": "^3.3.3"
      },
      "scripts": {
        "init:app": "node app"
      }
    }

    app.js
    进行模块的注册,目前包含了lodash以及一个自己的

     
    // setup plv8 connection
    const PLV8 = require('plv8')
    const knex = require('knex')
    const knexHandle = knex({
        client: 'pg',
        connection: {
          host: "127.0.0.1",
          user: "postgres",
          password: "dalong",
          database: "postgres"
        }
      })
    const plv8 = new PLV8(knexHandle)
    // setup a log listener
    plv8.on('log:error', msg => {
      console.error(msg)
    })
    // install the lodash module so that it can be loaded (via require()) later
    plv8.install({modulePath:require.resolve('lodash'),moduleName:"lodash"})
      .then(() => {
        // eval some code
        return plv8.eval(() => {
          const _ = require('lodash')
          return _.map([ 1, 2, 3 ], e => e + 1)
        })
      })
      .then(result => {
       console.log(result)
      }).catch(err=>{
          console.log(err)
      })
        plv8.install({modulePath:require.resolve("./login"),moduleName:"login"})
      .then(() => {
        // eval some code
        return plv8.eval(() => {
          const login = require('login')
          return login
        })
      })
      .then(result => {
       console.log(result)
      }).catch(err=>{
          console.log(err)
      })

    login.js 模块

    module.exports = {
        name:"dalong",
        age:333
    }

    运行&&测试

    • 启动docker 服务
    docker-compose up -d
    • 运行nodejs demo 服务
    yarn init:app
    • 效果
      目前有关于pg 通信的一些异常log,可能是和代码很就已经没维护,包版本兼容pg 的问题,后边
      调试研究下
     
    yarn run v1.17.3
    $ node app
    (node:56198) UnhandledPromiseRejectionWarning: error: syntax error at or near ":"
        at Connection.parseE (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:604:11)
        at Connection.parseMessage (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:401:19)
        at Socket.<anonymous> (/Users/dalong/mylearning/hasura-project/plv8/node-plv8/node_modules/pg/lib/connection.js:121:22)
        at Socket.emit (events.js:182:13)
        at addChunk (_stream_readable.js:283:12)
        at readableAddChunk (_stream_readable.js:264:11)
        at Socket.Readable.push (_stream_readable.js:219:10)
        at TCP.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
    (node:56198) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    (node:56198) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    Use async .hasTable to check if table exists and then use plain .createTable. Since .createTableIfNotExists actually just generates plain "CREATE TABLE IF NOT EXIST..." query it will not work correctly if there are any alter table queries generated for columns afterwards. To not break old migrations this function is left untouched for now, but it should not be used when writing new code and it is removed from documentation.
    Use async .hasTable to check if table exists and then use plain .createTable. Since .createTableIfNotExists actually just generates plain "CREATE TABLE IF NOT EXIST..." query it will not work correctly if there are any alter table queries generated for columns afterwards. To not break old migrations this function is left untouched for now, but it should not be used when writing new code and it is removed from documentation.
    { name: 'dalong', age: 333 }
    [ 2, 3, 4 ]
     

    sql 方式调用

    • 函数定义
    CREATE or replace FUNCTION dalong2() RETURNS json AS
    $$
        const login = require('login')
        return JSON.stringify(login);
    $$
    LANGUAGE plv8;
    • 查询
    SET plv8.start_proc = 'v8.plv8_init';
    select * from dalong2();
     
    • 效果
    {"name":"dalong","age":333}

    简单原理说明

    node plv8 将生成的js 通过browserify 以及babel 转换,存储在v8 schema 中的modules 表中
    同时注册了SET plv8.start_proc = 'v8.plv8_init'; 需要的plv8.init 函数,同时也注册了几个依赖的
    函数,代码的执行通过的是eval 函数,整体上还是比较简单的,但是实现的功能确实很方便的

    参考资料

    https://pgxn.org/dist/plv8/doc/plv8.html
    https://github.com/plv8/plv8
    https://plv8.github.io/
    https://github.com/rongfengliang/plv8-require-learning

  • 相关阅读:
    差分约束系统
    拓扑排序
    算法题笔记
    Pytorch学习笔记
    caffe增加新的layer
    跑实验技巧
    cmake & make入门
    CVPR2017_Learning Detailed Face Reconstruction from a Single Image
    Arxiv1801_PointCNN
    ICCV2015_Multi-view Convolutional Neural Networks for 3D Shape Recognition
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/11827441.html
Copyright © 2011-2022 走看看