Browse Source

Step 4: Connecting Node app to PostgreSQL.

Frederic G. MARAND 6 years ago
parent
commit
58c33d9d18
2 changed files with 84 additions and 9 deletions
  1. 34 3
      README.md
  2. 50 6
      node/src/server.js

+ 34 - 3
README.md

@@ -75,7 +75,7 @@ docker run -p 5432:5432             \
 
 ```bash
 # Without the -U, PG will try to use undeclared used root.  
-docker container exec -it psql -U postgres
+docker container exec -it voting-pg psql -U postgres
 ```
 * In `psql` in the container, list databases, create table, list tables:
 ```postgresql
@@ -99,8 +99,8 @@ CREATE TABLE votes (
 ```
   * Insert initial data
 ```postgresql
-INSERT INTO votes (id, number_of_votes, option_name) VALUES (1, 0, 'sandwiches');
-INSERT INTO votes (id, number_of_votes, option_name) VALUES (2, 0, 'tacos');
+INSERT INTO votes (id, number_of_votes, option_name) VALUES (1, 13, 'sandwiches');
+INSERT INTO votes (id, number_of_votes, option_name) VALUES (2, 21, 'tacos');
 SELECT * FROM votes;
 ```
   * Results:
@@ -111,3 +111,34 @@ SELECT * FROM votes;
   2 |               0 | tacos
 (2 rows)
 ```
+
+# Step 4: PG in Node app
+
+* To reach PG, the app needs to know the address. To get to it from inside the 
+container where the app runs, look for the `gateway` value in the results of 
+`docker bridge`:
+
+```
+[...snip...]
+    "IPAM": {
+            "Driver": "default",
+            "Options": null,
+            "Config": [
+                {
+                    "Subnet": "172.17.0.0/16",
+                    "Gateway": "172.17.0.1"
+                }
+            ]
+        },
+[...snip...]
+```
+
+* We then know that the IP to use in `client.connect()` will be `172.17.0.1`, at
+  least in the current configuration. Will probably have to come from the outside
+  for more flexibility.
+* Posting data to update:
+```bash
+curl -d"yourVote=sandwiches" http://localhost:8888/vote
+curl -d"yourVote=tacos"      http://localhost:8888/vote
+curl -d"yourVote=invalid"    http://localhost:8888/vote
+```

+ 50 - 6
node/src/server.js

@@ -4,13 +4,41 @@ const express = require('express');
 const app = express();
 const bodyParser = require('body-parser');
 const ejs = require('ejs');
-const ph = require('pg');
+const pg = require('pg');
+
+// Port number as seen from outside the PG container. Our run config maps the
+// internal 5432 to 9000 (beware machines with PHP-FPM on that port).
+// The IP is the "gateway" from "docker bridge"
+const client = new pg.Client('postgres://postgres@172.17.0.1:9000/postgres');
 
 const votes = {
   sandwiches: 0,
   tacos: 0,
 };
 
+client.connect((err, res) => {
+  if (err) {
+    throw err;
+  }
+
+  //language=PostgreSQL
+  const sql = `
+SELECT option_name, number_of_votes
+FROM votes
+ORDER BY id
+`;
+  client.query(sql, (err, res) => {
+    if (err) {
+      throw err;
+    }
+
+    for (const row of res.rows) {
+      votes[row.option_name] = row.number_of_votes;
+    }
+    console.log(votes);
+  });
+});
+
 const urlencodedParser = bodyParser.urlencoded({ extended: false });
 
 app.set('view engine', 'ejs');
@@ -24,14 +52,30 @@ app.get('/', function (req, res) {
 
 app.post('/vote', urlencodedParser, function (req, res) {
   const vote = req.body.yourVote;
-  if (vote == 'sandwiches') {
-    votes.sandwiches++;
-  }
-  else if (vote == 'tacos') {
-    votes.tacos++;
+
+  if (vote in votes) {
+    //language=PostgreSQL
+    const sql = `
+UPDATE votes
+SET number_of_votes = $1
+WHERE option_name = $2
+`;
+    const query = {
+      text: sql,
+      values: [votes[vote], vote]
+    };
+
+    votes[vote]++;
+    client.query(query, (err, res) => {
+      if (err) {
+        throw err;
+      }
+      console.log(`Rows modified for ${vote}: ${res.rowCount}.`);
+    });
   }
   else {
     console.log('Invalid vote:', vote);
+    // No query.
   }
 
   res.redirect('/');