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

posted on   荣锋亮  阅读(680)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2018-11-09 hangfire docker-compose 运行
2018-11-09 ballerina 学习 三十二 编写安全的程序
2017-11-09 npm 私服工具verdaccio 安装配置试用
2017-11-09 yarn 管理nextjs 项目
2017-11-09 jfrog artifactory jenkins pipeline 集成
2016-11-09 分布式id 实现方式
2013-11-09 警情处理软件设计的技术初步规划

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示