Using Snowflake in NextJS can't connect or execute queries in getStaticPaths/getStaticProps

906 views Asked by At

I've been tinkering around with NextJS for a bit now and am trying to convert an app to prerender static pages using getStaticProps and getStaticPaths with [id].js files for each page in their own separate folders (somthing like pages/posts/[id].js, /pages/articles/[id].js, etc.). Since those two functions are guaranteed to run on the server, I opted to move the fetch db functions from my public API to those functions directly. So within my [id].js files, I have something like this:

getStaticProps:

export async function getStaticProps({ params }) {
    let snowflake = require('snowflake-sdk')
    require('dotenv').config();
    let result = {};
    let id = params.id;

    const connection = snowflake.createConnection( {
        account: "account",
        username: "username",
        password: "password",
        warehouse: "warehouse"
    });
    
    console.log("Connecting to Snowflake...")
    await connection.connect( <- await doesn't seem to make a difference
        function(err, conn) {
            if (err) {
                console.error('Unable to connect: ' + err.message); <- This never outputs
            } 
            else {
                console.log('Successfully connected to Snowflake.'); <- Neither does this
            }
        }
    );

    await connection.execute({ <- await doesn't seem to make a difference
        sqlText: (`select stuff
                  from my_snowflake_db
                  where id=:1`),
        binds: [id],
        complete: function(err, stmt, data) {
            if (err) {
                console.error('Failed to execute statement due to the following error: ' + err.message);
            } else {
                result = data
                result["id"] = id
            }
        }
    })

    return {
        props: {
            result
        }
    }
}

getStaticPaths:

export async function getStaticPaths() {
    let snowflake = require('snowflake-sdk')
    require('dotenv').config();
    let paths = []

    const connection = snowflake.createConnection( {
        account: "account",
        username: "username",
        password: "password",
        warehouse: "warehouse"
    });
    
    console.log("Connecting to Snowflake...")
    await connection.connect( <- await doesn't seem to make a difference
        function(err, conn) {
            if (err) {
                console.error('Unable to connect: ' + err.message); <- This never outputs
            } 
            else {
                console.log('Successfully connected to Snowflake.'); <- Neither does this
            }
        }
    );

    await connection.execute({ <- await doesn't seem to make a difference
        sqlText: (`select id
                  from my_snowflake_db
                  where ...
                  `),
        complete: function(err, stmt, rows) {
            if (err) {
                console.error('Failed to execute statement due to the following error: ' + err.message); <- Never outputs
            } else {
                console.log("Got Response!") <- Never outputs
                for (var row in rows) {
                    console.log("Found id: " + row.id)
                    paths.push({
                        params: {
                            id: row.id
                        }
                    })
                }
            }
        }
    })

    console.log("Found paths: " + JSON.stringify(paths)) <- This outputs with an empty list

    return {
        paths,
        fallback: true
    }
}

When I build the app with npm run build, all I get are Connecting to Snowflake... and Found paths: [], then obviously getStaticProps breaks since the list is empty. I'm not sure why the connection can't be established, or why I'm not even getting error or success output. I'm assuming there's some issue with how Snowflake connects asynchronously, but I don't understand why the "await" keyword does nothing in this case. I can add or remove "await" and the result is the exact same.

2

There are 2 answers

0
Sergiu On

NextJS depends on NodeJS therefore following the steps from Snowflake documentation I got it working from first attempt.

This is my script:

async function connectToSnowflake(){
    let snowflake = require('snowflake-sdk');
    var connection = snowflake.createConnection({
        account: 'XXXXX',
        username: 'XXXXX',
        password: 'XXXXX' })
    await connection.connect(
        function(err,conn){
            if (err) {
                console.error('Unable to connect: ' + err.message);
            } else {
                console.log('Successfully connected');
                connection_ID = conn.getId();
                console.log(connection_ID);
            }
        }
    );
    await connection.execute({
        sqlText: 'select current_database()',
        complete: function(err,stmt, rows) {
            if (err) {
                console.error('Failed to execute statement due to the following error: ' + err.message);
            } else {
                console.log('Successfully executed statement: ' + stmt.getSqlText());
            }
        }
    });
}
connectToSnowflake();

Running this script I get:

[local@fedora nodejs]$ node connect_snowflake.js 
Successfully connected
90dfc5b0-a509-4d0a-8cfb-8022d02e8603
Successfully executed statement: select current_database()
[local@fedora nodejs]$ 

Try same and see if that works.

0
jacktim On

People trying to connect now. Make sure your account identifier i.e. org-name uses a '-' between and not a '.'. The account string copied from snowflake uses a . however it does not work, it must be a -