You should redesign your approach to use Long polling mechanism, use WebSosket or JSON streaming also will be an option.
A bit explanation:
You have a time-consuming task (takes 2 minutes, pretty sure it can take even more if your app will have more load). So, if you will use a simple Request-Respons approach, you will have an error because of timeout issues.
Because of that, using of proposed approaches will be better for your case.
Let's look at the WebSocket example:
In your go code, you will have something like(it's just an example to catch up an idea, I don't know chi and use github.com/gorilla/websocket
and vanilla net/http
but I'm pretty sure that you can do the same with chi):
package main
import (
"fmt"
"github.com/gorilla/websocket"
"log"
"net/http"
"time"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
func main() {
http.HandleFunc("/ws", wsHandler)
panic(http.ListenAndServe(":8080", nil))
}
func wsHandler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
if err != nil {
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
}
go echo(conn)
}
func echo(conn *websocket.Conn) {
defer conn.Close()
m := ""
err := conn.ReadJSON(&m)
if err != nil {
fmt.Println("Error reading json", err)
}
// receive some data from your reactjs
fmt.Printf("Got message: %#v\n", m)
om := struct {
mes string
}{
mes: "Send to client",
}
// send some data
if err = conn.WriteJSON(om); err != nil {
fmt.Println(err)
}
// do some work in 2 min
time.Sleep(120 * time.Second)
// send some data
if err = conn.WriteJSON(om); err != nil {
fmt.Println(err)
}
}
In your react js app you will have something like:
import React, { useState } from "react";
function App() {
let isDone = false;
const messages = []
const ws = new WebSocket("wss://localhost:8080/ws");
const apiCall = {
mes: "Your json for server"
};
ws.onopen = (event) => {
ws.send(JSON.stringify(apiCall));
};
ws.onmessage = function (event) {
const json = JSON.parse(event.data);
messages.push(json)
} catch (err) {
console.log(err);
}
};
ws.onclose = function (event) {
isDone = true
};
const mess = messages.map((item) => {
return (
<div>
<p> {item}</p>
</div>
);
});
return (
<div>
<div>{mess}</div>
<div> is work done?: {isDone}</div>
</div>
);
}
export default App;
In this example, we send some info to the server and start waiting when work will be finished(isDone = true
when ws
closed), meanwhile receiving some messages(maybe it's non needed in your case).
Same for implementation of this idea with Long polling and JSON streaming (I think you easily find something on the internet:) )