浏览代码

feat: Update referrers and countries in js

marvin-wtt 1 年之前
父节点
当前提交
00afd4f5ab
共有 2 个文件被更改,包括 47 次插入43 次删除
  1. 1 1
      .example.env
  2. 46 42
      server/queries/visit.queries.js

+ 1 - 1
.example.env

@@ -11,7 +11,7 @@ DEFAULT_DOMAIN=localhost:3000
 LINK_LENGTH=6
 
 # Postgres database credential details
-DB_CLIENT=postgresql
+DB_CLIENT=pg
 DB_HOST=localhost
 DB_PORT=5432
 DB_NAME=postgres

+ 46 - 42
server/queries/visit.queries.js

@@ -14,50 +14,54 @@ async function add(params) {
   const truncatedNow = new Date();
   truncatedNow.setMinutes(0, 0, 0);
 
-  // Create a subquery first that truncates the
-  const subquery = knex("visits")
-    .select("visits.*")
-    .select({
-      created_at_hours: utils.knexUtils(knex).truncatedTimestamp("created_at", "hour")
-    })
-    .where({ link_id: params.id })
-    .as("subquery");
-
-  const visit = await knex
-    .select("*")
-    .from(subquery)
-    .where("created_at_hours", "=", truncatedNow.toISOString())
-    .first();
-
-  if (visit) {
-    await knex("visits")
-      .where({ id: visit.id })
-      .increment(`br_${data.browser}`, 1)
-      .increment(`os_${data.os}`, 1)
-      .increment("total", 1)
-      .update({
-        updated_at: new Date().toISOString(),
-        countries: knex.raw(
-          "jsonb_set(countries, '{??}', (COALESCE(countries->>?,'0')::int + 1)::text::jsonb)",
-          [data.country, data.country]
-        ),
-        referrers: knex.raw(
-          "jsonb_set(referrers, '{??}', (COALESCE(referrers->>?,'0')::int + 1)::text::jsonb)",
-          [data.referrer, data.referrer]
-        )
+  return  knex.transaction(async (trx) => {
+    // Create a subquery first that truncates the
+    const subquery = trx("visits")
+      .select("visits.*")
+      .select({
+        created_at_hours: utils.knexUtils(trx).truncatedTimestamp("created_at", "hour")
+      })
+      .where({ link_id: params.id })
+      .as("subquery");
+
+    const visit = await trx
+      .select("*")
+      .from(subquery)
+      .where("created_at_hours", "=", truncatedNow.toISOString())
+      .forUpdate()
+      .first();
+
+    if (visit) {
+      await trx("visits")
+        .where({ id: visit.id })
+        .increment(`br_${data.browser}`, 1)
+        .increment(`os_${data.os}`, 1)
+        .increment("total", 1)
+        .update({
+          updated_at: new Date().toISOString(),
+          countries: {
+            ...visit.countries,
+            [data.country]: visit.countries[data.country] + 1
+          },
+          referrers: {
+            ...visit.referrers,
+             [data.referrer]: visit.referrers[data.referrer] + 1
+          }
+        });
+    } else {
+      // This must also happen in the transaction to avoid concurrency
+      await trx("visits").insert({
+        [`br_${data.browser}`]: 1,
+        countries: { [data.country]: 1 },
+        referrers: { [data.referrer]: 1 },
+        [`os_${data.os}`]: 1,
+        total: 1,
+        link_id: data.id
       });
-  } else {
-    await knex("visits").insert({
-      [`br_${data.browser}`]: 1,
-      countries: { [data.country]: 1 },
-      referrers: { [data.referrer]: 1 },
-      [`os_${data.os}`]: 1,
-      total: 1,
-      link_id: data.id
-    });
-  }
+    }
 
-  return visit;
+    return visit;
+  });
 }
 
 async function find(match, total) {