» Node.js: Building Event-Driven Microservices with Kafka » 4. Consumer: Recommendation Service » 4.4 Service Integration

Service Integration

Let‘s call the Recommendation Service to show user interests from the bookstore Web Service.

Add config items in src/web/infrastructure/config/config.ts:

@@ -17,6 +17,7 @@ interface MQConfig {
 
 export interface RemoteServiceConfig {
   trend_url: string;
+  rec_url: string;
 }
 
 export interface Config {

Put in config values in src/web/config.json:

@@ -12,6 +12,7 @@
     "topic": "lr-book-searches"
   },
   "remote": {
-    "trend_url": "http://localhost:3001/trends"
+    "trend_url": "http://localhost:3001/trends",
+    "rec_url": "http://localhost:3002/recommendations?uid="
   }
 }

Tune src/web/application/executor/book_operator.ts:

@@ -1,5 +1,5 @@
 import { BookManager } from "../../domain/gateway";
-import { Book, Trend } from "../../../domain/model";
+import { Book, Trend, Interest } from "../../../domain/model";
 import { MQHelper } from "../../infrastructure/mq";
 
 export class BookOperator {
@@ -36,4 +36,10 @@ export class BookOperator {
     const trends: Trend[] = await resp.json();
     return trends;
   }
+
+  async getInterests(recURL: string): Promise<Interest[]> {
+    const resp = await fetch(recURL);
+    const interests: Interest[] = await resp.json();
+    return interests;
+  }
 }

Integrate the recommendation service results in src/web/adapter/router.ts:

@@ -2,7 +2,7 @@ import express, { Request, Response } from "express";
 import cookieParser from "cookie-parser";
 import { engine } from "express-handlebars";
 
-import { Book, Trend } from "../../domain/model";
+import { Book, Interest, Trend } from "../../domain/model";
 import { BookOperator } from "../application/executor";
 import { WireHelper } from "../application";
 import { RemoteServiceConfig } from "../infrastructure/config";
@@ -39,12 +39,22 @@ class RestHandler {
       console.warn(`Failed to get trends: ${err}`);
       trends = [];
     }
+    let interests: Interest[];
+    try {
+      interests = await this.bookOperator.getInterests(
+        this.remote.rec_url + user_id
+      );
+    } catch (err) {
+      console.warn(`Failed to get interests: ${err}`);
+      interests = [];
+    }
     // Render the 'index.handlebars' template, passing data to it
     res.render("index", {
       layout: false,
       title: "LiteRank Book Store",
       books,
       trends,
+      recommendations: interests,
       q,
     });
   }

Render the recommendations in src/web/adapter/templates/index.handlebars:

@@ -60,17 +60,13 @@
         <!-- Recommended for You Section -->
         <div>
             <h2 class="text-2xl font-bold mb-4">Recommended for You</h2>
-            <div class="grid grid-cols-2 gap-4 font-mono">
-                <!-- Recommended items can be dynamically generated here -->
-                <div class="bg-white p-2 rounded-md border-gray-300 shadow">
-                    Recommended Book 1
-                </div>
-                <div class="bg-white p-2 rounded-md border-gray-300 shadow">
-                    Recommended Book 2
-                </div>
-                <div class="bg-white p-2 rounded-md border-gray-300 shadow">
-                    Recommended Book 3
+            <div class="grid grid-cols-4 gap-2 font-mono">
+                {{#each recommendations }}
+                <div class="bg-white p-4 rounded-md border-gray-300 shadow mt-2">
+                    <div class="text-lg font-bold">{{this.title}}</div>
+                    <span class="font-serif italic text-sm">{{this.author}}</span>
                 </div>
+                {{/each}}
             </div>
         </div>
     </div>

Make sure you have the trend and recommendation services running and restart your web service, you should see something like this on the index page.

Recommendations

Both services are integrated! Awesome🎉!