PureScript 中的全局资源(适用于 AWS Lambda)

Global Resources in PureScript(for AWS Lambda)

我想 运行 AWS Lambda 中的 PureScript 代码。通常,如果 lambda 函数必须调用数据库,则连接存储在全局变量中。对不起,如果以下 JavaScript 代码在语法上是错误的,因为我没有写 JavaScript 但下面是我想要的(这是 AWS Lambda 期望的代码):

function createConnection() {
    connection = SomeDBLibrary.createConnection(username, pwd)
    return connection;
}
global.db_connection = createConnection();

handler = (event, context, callback) => {
    // TODO use global.db_connection here to call the database
};

module.exports {
 handler: handler
};

如何编写等效的 PureScript 来获得此类代码?目前,我在我的每个 CRUD 方法中调用 createConnection() 函数,这很浪费。

编辑 1:

我的实际 PureScript 代码如下。我只想调用一次的函数是aPool。但是,我相信每次点击 /list 端点时都会调用它。我希望它在第一次加载处理程序时只被命中一次。

module Main where

import Prelude hiding (apply)

import Data.Bifunctor (lmap)
import Data.Either (Either)
import Database.Postgres (Client, ClientConfig, ConnectionInfo, Pool, Query(Query), connectionInfoFromConfig, defaultPoolConfig, mkPool, query_, withClient)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff.Class (liftAff)
import Effect.Class (class MonadEffect, liftEffect)
import Effect.Console (log)
import Effect.Exception (Error, error)
import Foreign (Foreign)
import Node.Express.App (App, get)
import Node.Express.Handler (Handler)
import Node.Express.Response (sendJson)
import Simple.JSON as JSON
import Network.AWS.Lambda.Express as Lambda


clientConfig :: ClientConfig
clientConfig =
  { host: "localhost"
  , database: "test"
  , port: 5432
  , user: "testuser"
  , password: "test"
  , ssl: false
  }

type IndexedTodo = { id :: Int, description :: String, isdone :: Boolean }

connectionInfo :: ConnectionInfo
connectionInfo = connectionInfoFromConfig clientConfig defaultPoolConfig

println :: forall a. MonadEffect a => String -> a Unit
println str =  liftEffect $ log str

aPool :: Effect Pool
aPool = do
  println "In Pooler"
  mkPool connectionInfo

withConnectionPool :: forall a. Effect Pool -> (Client -> Aff a) -> Aff a
withConnectionPool somePool f = do
  pool <- liftEffect somePool
  withClient pool \c -> f c

withConnection :: forall a. (Client -> Aff a) -> Aff a
withConnection = withConnectionPool aPool

read' :: forall a. JSON.ReadForeign a => Foreign -> Either Error a
read' = lmap (error <<< show) <<< JSON.read

readTodoList :: Aff (Array IndexedTodo)
readTodoList = do
  let selectQuery = Query "select * from todos" :: Query IndexedTodo
  withConnection $ query_ read' selectQuery

listTodosHandler :: Handler
listTodosHandler = do
  userdata <- liftAff readTodoList
  sendJson userdata


app :: App
app = do
  get "/list"       listTodosHandler

-- Define the AWS Lambda handler
handler :: Lambda.HttpHandler
handler = Lambda.makeHandler app

我认为这需要像这样的 FFI:

foreign import dbConnection :: Effect Connection

实施:

exports.dbConnection = function() {
  if(globals.dbConnection === undefined) {
    globals.dbConnection = createConnection();
  }
  return globals.dbConnection;
}