Skip to content

Commit 282f5dd

Browse files
authored
Merge pull request #5 from AJackTi/feature/communication_rpc
Feat: Communicating between services using Remote Procedure Calls (RPC)
2 parents c12d3ae + b04c681 commit 282f5dd

File tree

4 files changed

+134
-12
lines changed

4 files changed

+134
-12
lines changed

broker-service/cmd/api/handlers.go

+36
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"log"
1010
"net/http"
11+
"net/rpc"
1112
)
1213

1314
type RequestPayload struct {
@@ -61,6 +62,9 @@ func (app *Config) HandleSubmission(w http.ResponseWriter, r *http.Request) {
6162
case "mail":
6263
app.sendMail(w, requestPayload.Mail)
6364

65+
case "log-via-rpc":
66+
app.logItemViaRPC(w, requestPayload.Log)
67+
6468
case "log-event":
6569
app.logEventViaRabbit(w, requestPayload.Log)
6670

@@ -227,3 +231,35 @@ func (app *Config) pushToQueue(name, msg string) error {
227231

228232
return nil
229233
}
234+
235+
type RPCPayload struct {
236+
Name string
237+
Data string
238+
}
239+
240+
func (app *Config) logItemViaRPC(w http.ResponseWriter, l LogPayload) {
241+
client, err := rpc.Dial("tcp", "logger-service-app:5001")
242+
if err != nil {
243+
app.errorJSON(w, err)
244+
return
245+
}
246+
247+
rpcPayload := RPCPayload{
248+
Name: l.Name,
249+
Data: l.Data,
250+
}
251+
252+
var result string
253+
err = client.Call("RPCServer.LogInfo", rpcPayload, &result)
254+
if err != nil {
255+
app.errorJSON(w, err)
256+
return
257+
}
258+
259+
payload := jsonResponse{
260+
Error: false,
261+
Message: result,
262+
}
263+
264+
app.writeJSON(w, http.StatusAccepted, payload)
265+
}

front-end/cmd/web/templates/test.page.gohtml

+36
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<a href="javascript:void(0);" id="logBtn" class="btn btn-outline-secondary">Test log</a>
1111
<a href="javascript:void(0);" id="mailBtn" class="btn btn-outline-secondary">Test mail</a>
1212
<a href="javascript:void(0);" id="listenerBtn" class="btn btn-outline-secondary">Test listener</a>
13+
<a href="javascript:void(0);" id="logViaRPCBtn" class="btn btn-outline-secondary">Test log via RPC</a>
1314

1415
<div id="output" class="mt-5" style="outline: 1px solid silver; padding: 2em;">
1516
<span class="text-muted">Output shows here...</span>
@@ -38,6 +39,7 @@
3839
let logBtn = document.getElementById("logBtn");
3940
let mailBtn = document.getElementById("mailBtn");
4041
let listenerBtn = document.getElementById("listenerBtn");
42+
let logViaRPCBtn = document.getElementById("logViaRPCBtn");
4143
let output = document.getElementById("output");
4244
let sent = document.getElementById("payload");
4345
let received = document.getElementById("received");
@@ -76,6 +78,40 @@
7678
})
7779
})
7880

81+
logViaRPCBtn.addEventListener("click", function() {
82+
const payload = {
83+
action: "log-via-rpc",
84+
log: {
85+
name: "event",
86+
data: "Some kind of data",
87+
}
88+
}
89+
90+
const headers = new Headers();
91+
headers.append("Content-Type", "application/json");
92+
93+
const body = {
94+
method: "POST",
95+
body: JSON.stringify(payload),
96+
headers: headers,
97+
}
98+
99+
fetch("http:\/\/localhost:8080/handle", body)
100+
.then((response) => response.json())
101+
.then((data) => {
102+
sent.innerHTML = JSON.stringify(payload, undefined, 4);
103+
received.innerHTML = JSON.stringify(data, undefined, 4);
104+
if (data.error) {
105+
output.innerHTML += ` <br><strong> Error: </strong> ${data.message}`;
106+
} else {
107+
output.innerHTML += `<br><strong>Response from broker service</strong>: ${data.message}`;
108+
}
109+
})
110+
.catch((error) => {
111+
output.innerHTML += "<br><br>Eror: " + error;
112+
})
113+
})
114+
79115
mailBtn.addEventListener("click", function() {
80116
const payload = {
81117
action: "mail",

logger-service/cmd/api/main.go

+25-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"fmt"
66
"log"
77
"log-service/data"
8+
"net"
89
"net/http"
10+
"net/rpc"
911
"time"
1012

1113
"go.mongodb.org/mongo-driver/mongo"
@@ -48,8 +50,11 @@ func main() {
4850
Models: *data.New(client),
4951
}
5052

53+
// Register the RPC Server
54+
err = rpc.Register(new(RPCServer))
55+
go app.rpcListen()
56+
5157
// start web server
52-
// go app.serve()
5358
log.Println("Starting service on port", webPort)
5459
srv := &http.Server{
5560
Addr: fmt.Sprintf(":%s", webPort),
@@ -62,17 +67,25 @@ func main() {
6267
}
6368
}
6469

65-
// func (app *Config) serve() {
66-
// srv := &http.Server{
67-
// Addr: fmt.Sprintf(":%s", webPort),
68-
// Handler: app.routes(),
69-
// }
70-
71-
// err := srv.ListenAndServe()
72-
// if err != nil {
73-
// log.Panic(err)
74-
// }
75-
// }
70+
func (app *Config) rpcListen() error {
71+
log.Println("Starting RPC server on port", rpcPort)
72+
listen, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%s", rpcPort))
73+
if err != nil {
74+
log.Println(err)
75+
return err
76+
}
77+
defer listen.Close()
78+
79+
for {
80+
rpcConn, err := listen.Accept()
81+
if err != nil {
82+
log.Println(err)
83+
continue
84+
}
85+
86+
go rpc.ServeConn(rpcConn)
87+
}
88+
}
7689

7790
func connectToMongo() (*mongo.Client, error) {
7891
// create connection options

logger-service/cmd/api/rpc.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
"log-service/data"
7+
"time"
8+
)
9+
10+
// RPCServer is the type for our RPC Server. Methods that take this as a receiver are avaiable
11+
// over RPC, as long as they are exported.
12+
type RPCServer struct {
13+
}
14+
15+
// RPCPayload is the type for data we receive from RPC
16+
type RPCPayload struct {
17+
Name string
18+
Data string
19+
}
20+
21+
// LogInfo writes our payload to mongo
22+
func (r *RPCServer) LogInfo(payload RPCPayload, resp *string) error {
23+
collection := client.Database("logs").Collection("logs")
24+
_, err := collection.InsertOne(context.TODO(), data.LogEntry{
25+
Name: payload.Name,
26+
Data: payload.Data,
27+
CreatedAt: time.Now(),
28+
})
29+
if err != nil {
30+
log.Println("error writing to mongo", err)
31+
return err
32+
}
33+
34+
*resp = "Processed payload via RPC: " + payload.Name
35+
36+
return nil
37+
}

0 commit comments

Comments
 (0)