1

Running into an H12 timeout error when going to a GET route to seed my Heroku database with product data. I created the get route (/products/SEEDALLPRODUCTS) which executes the SeedProducts.seed class method, however it looks like the error raises right before the first db.query occurs. I know this isn't the most efficient method, however it worked on my local server and not sure why I'm getting errors with heroku.

The error:

2021-03-27T22:42:47.394930+00:00 app[web.1]: GET /products/SEEDALLPRODUCTS - - - - ms 2021-03-27T22:42:47.395489+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/products/SEEDALLPRODUCTS" host=freebay-backend.herokuapp.com request_id=c8b5fc3f-49d8-4465-9b44-71ccfa2923ec fwd="24.119.49.241" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https

The route:

/** Routes for products. */

// const jsonschema = require("jsonschema");
const express = require("express");
const SeedProducts = require("../FreebaySeed");

// Seeds all products to database.
// Only to be called once at projects deployment
const router = new express.Router();
router.get("/SEEDALLPRODUCTS", async function (req, res, next) {
  try {
    const products = await SeedProducts.seed();
    console.log("products",products)
    return res.json("Successfully seeded products to database!");
  } catch (err) {
    return next(err);
  }
});

The class

"use strict";

const products1 = require("./products_1");
const products2 = require("./products_2");
const products3 = require("./products_3");

const db = require("./db");

class SeedProducts{

  static randomCondition(){
    const conditions = ["Brand New", "New - Open Box", "Good", "Used"]
    const condition = conditions[(Math.floor(Math.random() * 4))]
    return condition
  }

  static randomDate(start, end) {
    console.log("start",start)
    console.log("end",end)
    console.log("end.getTime() - start.getTime()",(end.getTime() - start.getTime()))

    let currentDateTime = new Date()

    return new Date(currentDateTime.getTime() + Math.random() * (36400000));
  }

  static randomRating() {
    return ((Math.floor(Math.random() * 4))+2)
  }
  
  static randomNumberOfRatings() {
    return (Math.floor(Math.random() * 1111))
  }

/** Method to seed all products into database */

  static async seed() {
   
    for (let i = 0; i < products1.length; i++) {
      console.log("[i]",[i])
      console.log("products1[i]",products1[i])
      const {item, category, sub_category, description, image_1, market_price} = products1[i]

      // Create Random DateTime object
      let auction_end_dt = SeedProducts.randomDate(new Date(2021, 3, 25), new Date())
      console.log("auction_end_dt in FreebaySeed.js", auction_end_dt)

      // Create starting price as 2/3 of the product's actual price
      let starting_bid = Math.round(market_price * .66)
      starting_bid = Math.round(100*starting_bid)/100
      console.log("starting_bid in FreebaySeed.js", starting_bid)


      // Grab random rating, number of ratings, and condition
      const num_of_ratings = SeedProducts.randomNumberOfRatings()
      const rating = SeedProducts.randomRating()
      const condition = SeedProducts.randomCondition()
      console.log("num_of_ratings in FreebaySeed.js", num_of_ratings)
      console.log("rating in FreebaySeed.js", rating)
      console.log("condition in FreebaySeed.js", condition)

      const valuesArray =
        [item, category, sub_category, description, condition, rating, num_of_ratings, image_1, starting_bid, auction_end_dt]

      await db.query(`INSERT INTO products (name, category, sub_category, description, condition, rating, num_of_ratings, image_url, starting_bid, auction_end_dt) 
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, valuesArray)
      }
    
    for (let i = 0; i < products2.length; i++) {
      console.log(i)
      const {item, category, sub_category, description, image_1, market_price} = products2[i]

      // Create Random DateTime object
      let auction_end_dt = SeedProducts.randomDate(new Date(2021, 3, 25), new Date())
      console.log("auction_end_dt", auction_end_dt)

      // Create starting price as half of the product's actual price
      let starting_bid = market_price * .5
      starting_bid = Math.round(100*starting_bid)/100

      // Grab random rating and number of ratings
      const num_of_ratings = SeedProducts.randomNumberOfRatings()
      const rating = SeedProducts.randomRating()
      const condition = SeedProducts.randomCondition()

      const valuesArray =
        [item, category, sub_category, description, condition, rating, num_of_ratings, image_1, starting_bid, auction_end_dt]

      await db.query(`INSERT INTO products (name, category, sub_category, description, condition, rating, num_of_ratings, image_url, starting_bid, auction_end_dt) 
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, valuesArray)
      }

    for (let i = 0; i < products3.length; i++) {
      console.log(i)
      const {item, category, sub_category, description, image_1, market_price} = products3[i]

      // Create Random DateTime object
      let auction_end_dt = SeedProducts.randomDate(new Date(2021, 3, 25), new Date())
      console.log("auction_end_dt", auction_end_dt) 

      // Create starting price as half of the product's actual price
      let starting_bid = market_price * .5
      starting_bid = Math.round(100*starting_bid)/100

      // Grab random rating and number of ratings
      const num_of_ratings = SeedProducts.randomNumberOfRatings()
      const rating = SeedProducts.randomRating()
      const condition = SeedProducts.randomCondition()

      console.log("item", item)
      const valuesArray =
        [item, category, sub_category, description, condition, rating, num_of_ratings, image_1, starting_bid, auction_end_dt]

      await db.query(`INSERT INTO products (name, category, sub_category, description, condition, rating, num_of_ratings, image_url, starting_bid, auction_end_dt) 
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, valuesArray)
      }
    }
}

module.exports = SeedProducts;

The products_1.js, products_2.js, and products_3.js are three massive files each containing an array of objects.

https://github.com/Bolmstead/freebay-backend/blob/master/products_1.js https://github.com/Bolmstead/freebay-backend/blob/master/products_2.js https://github.com/Bolmstead/freebay-backend/blob/master/products_3.js

Just curious why I am getting this error so I can create a workaround. Thanks in advance

1 Answers1

1

From what I understand, you seed your application's database by sending it a GET request? IMHO this does not sound like a good idea to allow anyone over the internet to seed your database like that.

Does your application use a framework? There should be a command to seed your database. I know that for a rails app, one can run the following command to seed:

heroku run rails db:seed

You could also copy the scripts and execute them directly on the server. Another possibility would be to execute them locally and then push your database to heroku.

ryanzidago
  • 358
  • 2
  • 7
  • 1
    Wow, had no clue you can push your entire local database to heroku. Thank you for that! Just tried running `heroku run node FreebaySeed.js` and ran into the error ` UnhandledPromiseRejectionWarning: error: no pg_hba.conf entry for host...` I'm sure it is an error within my code, so looking into past StackOverflow posts to see if I can find anything – personwholikestocode Mar 28 '21 at 03:49
  • Have you tried to activate SSL? Heroku requires now that SSL is activated on production application. See maybe here for a fix https://stackoverflow.com/questions/60048669/heroku-postgres-psql-fatal-no-pg-hba-conf-entry-for-host and here for the documentation: https://help.heroku.com/DR0TTWWD/seeing-fatal-no-pg_hba-conf-entry-errors-in-postgres – ryanzidago Mar 28 '21 at 06:48