1
votes

I would like to run PureScript code in AWS Lambda. Normally, if a lambda function has to call the database, the connection is stored in a global variable. Excuse me if the following JavaScript code is syntactically wrong as I don't write JavaScript but something like below is what I want(this is the code expected by 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
};

How do I write the equivalent PureScript to get such code? Currently, I call the createConnection() function in each of my CRUD methods which is wasteful.

Edit 1:

My actual PureScript code is below. The function which I want to call only once is aPool. However, I believe it's being called everytime one hits the /list endpoint. I would like it to be hit only once when the handler is loaded for the first time.

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
1

1 Answers

1
votes

I think that this requires a FFI like:

foreign import dbConnection :: Effect Connection

with implementation:

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