Skip to content

Commit d5855ff

Browse files
Merge pull request #2 from Astrasv/feature/volpe-integration
Feature: Communication enabled with VolPE integrator service and Added basic dev docs
2 parents 2828e6c + a4692ce commit d5855ff

8 files changed

Lines changed: 409 additions & 132 deletions

File tree

ARCHITECTURE.md

Lines changed: 0 additions & 89 deletions
This file was deleted.

README.md

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,65 @@
1-
# controller_microservice_v2
2-
Source code of controller microservice that handles data to and from frontend and jupyter kernel gateway for evolutionary algorithms on click v2
1+
# Controller Microservice V2
2+
3+
Source code of controller microservice that handles data to and from frontend and jupyter kernel gateway for evolutionary algorithms on click v2.
4+
5+
## Overview
6+
7+
This service acts as the central orchestrator for the platform, managing:
8+
- [User Sessions & Authentication](https://github.com/Evolutionary-Algorithms-On-Click/auth_microservice)
9+
- Jupyter Kernel Lifecycle (via `jupyter_gateway`)
10+
- Database Interactions (CockroachDB)
11+
- Inter-service communication (gRPC, HTTP)
12+
- [LLM microservice ](https://github.com/Evolutionary-Algorithms-On-Click/evocv2_llm_microservice)
13+
- [Volpe Integration service](https://github.com/Evolutionary-Algorithms-On-Click/volpe-integration)
14+
15+
## Prerequisites
16+
17+
- **Go**: 1.24.1 or higher
18+
- **Docker**: For containerization and dependencies (CockroachDB, MinIO, )
19+
- **Docker Compose**: For orchestration
20+
- **Make**: For running standard commands
21+
- **Lefthook**: For git hooks (optional but recommended)
22+
23+
## Getting Started
24+
25+
### 1. Environment Setup
26+
27+
1. Clone the repository.
28+
2. Ensure you have the necessary environment variables set. Refer to `docker-compose.yaml` for required keys (e.g., `DATABASE_URL`, `JUPYTER_GATEWAY_URL`).
29+
*Note: The project uses `godotenv` to load environment variables from a `.env` file in development.*
30+
31+
### 2. Running Dependencies
32+
33+
Start the supporting services (Database, Object Storage, Jupyter Gateway, etc.):
34+
35+
```bash
36+
make docker-up
37+
```
38+
39+
or
40+
41+
```bash
42+
docker-compose up --build
43+
```
44+
45+
46+
This will spin up CockroachDB, MinIO, Jupyter Gateway, and Python Runner as defined in `docker-compose.yaml`.
47+
48+
### 3. Local Development
49+
50+
To run the controller service locally:
51+
52+
```bash
53+
# Install tools and git hooks
54+
make setup
55+
56+
# Build and run the application
57+
make run
58+
```
59+
60+
The service will start on port `8080` (default).
61+
62+
## API Documentation
63+
64+
- **HTTP API**: Versioned under `/api/v1/`. Defined in `routes/api.go`.
65+
- **gRPC**: Defined in `proto/authenticate.proto`.

controllers/problem_controller.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package controllers
33
import (
44
"context"
55
"encoding/json"
6+
"errors"
67
"fmt"
8+
"io"
79
"log"
810
"net/http"
911
"time"
@@ -212,3 +214,94 @@ func (c *ProblemController) DeleteProblemByIDHandler(w http.ResponseWriter, r *h
212214
c.Logger.Info().Str("problemID", problemID).Msg("successfully deleted problem by ID")
213215
w.WriteHeader(http.StatusNoContent)
214216
}
217+
218+
// SubmitNotebookHandler handles POST /api/v1/submission/submit
219+
func (c *ProblemController) SubmitNotebookHandler(w http.ResponseWriter, r *http.Request) {
220+
c.Logger.Info().Msg("received request to submit notebook")
221+
222+
user, ok := r.Context().Value(middleware.UserContextKey).(*middleware.User)
223+
if !ok {
224+
c.Logger.Error().Msg("user not found in context for submission")
225+
http.Error(w, "user not found in context", http.StatusUnauthorized)
226+
return
227+
}
228+
229+
type submitRequest struct {
230+
NotebookID string `json:"notebook_id"`
231+
Filename string `json:"filename"`
232+
SessionID string `json:"session_id"`
233+
}
234+
235+
var req submitRequest
236+
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
237+
c.Logger.Error().Err(err).Msg("invalid request body for submission")
238+
http.Error(w, "invalid request body", http.StatusBadRequest)
239+
return
240+
}
241+
242+
if req.NotebookID == "" || req.Filename == "" || req.SessionID == "" {
243+
http.Error(w, "notebook_id, filename, and session_id are required", http.StatusBadRequest)
244+
return
245+
}
246+
247+
// We don't limit the context time here as submission might take time, or we rely on default timeouts
248+
ctx := r.Context()
249+
250+
result, err := c.ProblemModule.SubmitNotebook(ctx, user.ID, req.NotebookID, req.SessionID, req.Filename)
251+
if err != nil {
252+
c.Logger.Error().Err(err).Msg("failed to submit notebook")
253+
http.Error(w, fmt.Sprintf("failed to submit notebook: %v", err), http.StatusInternalServerError)
254+
return
255+
}
256+
257+
pkg.WriteJSONResponseWithLogger(w, http.StatusOK, result, &c.Logger)
258+
}
259+
260+
// GetSubmissionResultsHandler handles GET /api/v1/submission/results/{problemId}
261+
func (c *ProblemController) GetSubmissionResultsHandler(w http.ResponseWriter, r *http.Request) {
262+
problemID := r.PathValue("problemId")
263+
c.Logger.Info().Str("problemID", problemID).Msg("received request to get submission results")
264+
265+
ctx := r.Context()
266+
267+
// Connect to volpe and get the stream
268+
stream, err := c.ProblemModule.GetSubmissionResults(ctx, problemID)
269+
if err != nil {
270+
c.Logger.Error().Err(err).Msg("failed to get results stream")
271+
http.Error(w, fmt.Sprintf("failed to get results: %v", err), http.StatusInternalServerError)
272+
return
273+
}
274+
defer stream.Close()
275+
276+
w.Header().Set("Content-Type", "text/event-stream")
277+
w.Header().Set("Cache-Control", "no-cache")
278+
w.Header().Set("Connection", "keep-alive")
279+
280+
flusher, ok := w.(http.Flusher)
281+
if !ok {
282+
http.Error(w, "streaming not supported", http.StatusInternalServerError)
283+
return
284+
}
285+
286+
buf := make([]byte, 1024)
287+
for {
288+
n, err := stream.Read(buf)
289+
if n > 0 {
290+
if _, wErr := w.Write(buf[:n]); wErr != nil {
291+
c.Logger.Error().Err(wErr).Msg("failed to write to response")
292+
break
293+
}
294+
flusher.Flush()
295+
}
296+
if err != nil {
297+
if err != io.EOF {
298+
if errors.Is(err, context.Canceled) {
299+
c.Logger.Info().Msg("client disconnected from submission results stream")
300+
} else {
301+
c.Logger.Error().Err(err).Msg("error reading from volpe stream")
302+
}
303+
}
304+
break
305+
}
306+
}
307+
}

0 commit comments

Comments
 (0)