about summary refs log tree commit diff
path: root/src/rest-api
diff options
context:
space:
mode:
Diffstat (limited to 'src/rest-api')
-rw-r--r--src/rest-api/cmd/BUILD.bazel1
-rw-r--r--src/rest-api/cmd/main.go14
-rw-r--r--src/rest-api/handler/BUILD.bazel27
-rw-r--r--src/rest-api/handler/db.go37
-rw-r--r--src/rest-api/handler/handler.go38
-rw-r--r--src/rest-api/handler/handler_test.go31
-rw-r--r--src/rest-api/handler/mock_db.go56
7 files changed, 198 insertions, 6 deletions
diff --git a/src/rest-api/cmd/BUILD.bazel b/src/rest-api/cmd/BUILD.bazel
index 4ecded7..0d96a1f 100644
--- a/src/rest-api/cmd/BUILD.bazel
+++ b/src/rest-api/cmd/BUILD.bazel
@@ -11,6 +11,7 @@ go_library(
     visibility = ["//visibility:private"],
     deps = [
         "//src/rest-api/handler",
+        "@com_github_jmoiron_sqlx//:sqlx",
         "@com_github_segmentio_kafka_go//:kafka-go",
         "@com_github_segmentio_kafka_go//sasl/plain",
     ],
diff --git a/src/rest-api/cmd/main.go b/src/rest-api/cmd/main.go
index d1e44b3..98f3722 100644
--- a/src/rest-api/cmd/main.go
+++ b/src/rest-api/cmd/main.go
@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/Baitinq/fs-tracer-backend/src/rest-api/handler"
+	"github.com/jmoiron/sqlx"
 	"github.com/segmentio/kafka-go"
 	"github.com/segmentio/kafka-go/sasl/plain"
 )
@@ -47,13 +48,22 @@ func main() {
 		AllowAutoTopicCreation: true,
 	}
 
-	handler := handler.NewHandler(kafka_writer)
+	db_password, ok := os.LookupEnv("DB_PASSWORD")
+	if !ok {
+		log.Fatal("DB_PASSWORD not set")
+	}
+	db, err := sqlx.Connect("postgres", fmt.Sprintf("postgres://postgres.slpoocycjgqsuoedhkbn:%s@aws-0-eu-central-1.pooler.supabase.com:5432/postgres", db_password))
+	if err != nil {
+		log.Fatal("cannot initalize db client", err)
+	}
+
+	handler := handler.NewHandler(db, kafka_writer)
 
 	mux := http.NewServeMux()
 	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		fmt.Fprint(w, "Hello folks!")
 	})
-	mux.Handle("/payload", handler)
+	mux.Handle("/file/", handler)
 
 	http.ListenAndServe(":8080", mux)
 }
diff --git a/src/rest-api/handler/BUILD.bazel b/src/rest-api/handler/BUILD.bazel
index 89adc69..e588929 100644
--- a/src/rest-api/handler/BUILD.bazel
+++ b/src/rest-api/handler/BUILD.bazel
@@ -1,9 +1,30 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
+load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
 
 go_library(
     name = "handler",
-    srcs = ["handler.go"],
+    srcs = [
+        "db.go",
+        "handler.go",
+        "mock_db.go",
+    ],
     importpath = "github.com/Baitinq/fs-tracer-backend/src/rest-api/handler",
     visibility = ["//visibility:public"],
-    deps = ["@com_github_segmentio_kafka_go//:kafka-go"],
+    deps = [
+        "//lib",
+        "@com_github_jmoiron_sqlx//:sqlx",
+        "@com_github_lib_pq//:pq",
+        "@com_github_segmentio_kafka_go//:kafka-go",
+        "@org_uber_go_mock//gomock",
+    ],
+)
+
+go_test(
+    name = "handler_test",
+    srcs = ["handler_test.go"],
+    embed = [":handler"],
+    deps = [
+        "//lib",
+        "@com_github_stretchr_testify//require",
+        "@org_uber_go_mock//gomock",
+    ],
 )
diff --git a/src/rest-api/handler/db.go b/src/rest-api/handler/db.go
new file mode 100644
index 0000000..0093c41
--- /dev/null
+++ b/src/rest-api/handler/db.go
@@ -0,0 +1,37 @@
+package handler
+
+import (
+	"context"
+
+	"github.com/Baitinq/fs-tracer-backend/lib"
+	"github.com/jmoiron/sqlx"
+)
+
+//go:generate mockgen -source=$GOFILE -package=$GOPACKAGE -destination=mock_$GOFILE
+type DB interface {
+	GetLatestFileByPath(ctx context.Context, path string) (*lib.File, error)
+}
+
+type DBImpl struct {
+	db *sqlx.DB
+}
+
+var _ DB = (*DBImpl)(nil)
+
+func NewDB(db *sqlx.DB) DB {
+	return &DBImpl{db: db}
+}
+
+func (db DBImpl) GetLatestFileByPath(ctx context.Context, path string) (*lib.File, error) {
+	var file lib.File
+	err := db.db.GetContext(ctx, &file, `
+		SELECT * FROM private.file
+		WHERE absolute_path = $1
+		ORDER BY timestamp DESC
+		LIMIT 1
+	`, path)
+	if err != nil {
+		return nil, err
+	}
+	return &file, nil
+}
diff --git a/src/rest-api/handler/handler.go b/src/rest-api/handler/handler.go
index 9e44612..558e773 100644
--- a/src/rest-api/handler/handler.go
+++ b/src/rest-api/handler/handler.go
@@ -6,22 +6,58 @@ import (
 	"io"
 	"log"
 	"net/http"
+	"strings"
 	"time"
 
+	"github.com/jmoiron/sqlx"
+	_ "github.com/lib/pq"
 	"github.com/segmentio/kafka-go"
 )
 
 type Handler struct {
+	db           DB
 	kafka_writer *kafka.Writer
 }
 
-func NewHandler(kafka_writer *kafka.Writer) Handler {
+func NewHandler(db *sqlx.DB, kafka_writer *kafka.Writer) Handler {
 	return Handler{
+		db:           NewDB(db),
 		kafka_writer: kafka_writer,
 	}
 }
 
 func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	switch r.Method {
+	case http.MethodGet:
+		h.handleGet(w, r)
+	case http.MethodPost:
+		h.handlePost(w, r)
+	default:
+		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+	}
+}
+
+func (h Handler) handleGet(w http.ResponseWriter, r *http.Request) {
+	_, filePath, ok := strings.Cut(r.URL.Path, "/file/")
+	if !ok {
+		http.Error(w, "Invalid file path", http.StatusBadRequest)
+		return
+	}
+
+	log.Println("File path: ", filePath)
+
+	ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
+	defer cancel()
+	file, err := h.db.GetLatestFileByPath(ctx, filePath)
+	if err != nil {
+		http.Error(w, fmt.Sprintf("Internal server error: %s", err), http.StatusInternalServerError)
+		return
+	}
+
+	fmt.Fprintln(w, "File: ", file)
+}
+
+func (h Handler) handlePost(w http.ResponseWriter, r *http.Request) {
 	bytes, err := io.ReadAll(io.Reader(r.Body))
 	if err != nil {
 		log.Fatal(err)
diff --git a/src/rest-api/handler/handler_test.go b/src/rest-api/handler/handler_test.go
new file mode 100644
index 0000000..94b58e4
--- /dev/null
+++ b/src/rest-api/handler/handler_test.go
@@ -0,0 +1,31 @@
+package handler
+
+import (
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+
+	"github.com/Baitinq/fs-tracer-backend/lib"
+	"github.com/stretchr/testify/require"
+	gomock "go.uber.org/mock/gomock"
+)
+
+func TestHandleGet(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	db := NewMockDB(ctrl)
+	recorder := httptest.NewRecorder()
+
+	handler := Handler{db: db}
+
+	file := &lib.File{
+		Absolute_path: "/tmp/file.txt",
+	}
+	db.EXPECT().GetLatestFileByPath(gomock.Any(), "/tmp/file.txt").Return(file, nil)
+
+	handler.handleGet(recorder, httptest.NewRequest(http.MethodGet, "/file/%2ftmp%2Ffile.txt", nil))
+
+	require.Equal(t, http.StatusOK, recorder.Code)
+	require.Equal(t, fmt.Sprintln("File: ", file), recorder.Body.String())
+}
diff --git a/src/rest-api/handler/mock_db.go b/src/rest-api/handler/mock_db.go
new file mode 100644
index 0000000..2d51a8f
--- /dev/null
+++ b/src/rest-api/handler/mock_db.go
@@ -0,0 +1,56 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: src/rest-api/handler/db.go
+//
+// Generated by this command:
+//
+//	mockgen -source src/rest-api/handler/db.go -package handler -destination=src/rest-api/handler/mock_db.go
+//
+
+// Package handler is a generated GoMock package.
+package handler
+
+import (
+	context "context"
+	reflect "reflect"
+
+	lib "github.com/Baitinq/fs-tracer-backend/lib"
+	gomock "go.uber.org/mock/gomock"
+)
+
+// MockDB is a mock of DB interface.
+type MockDB struct {
+	ctrl     *gomock.Controller
+	recorder *MockDBMockRecorder
+}
+
+// MockDBMockRecorder is the mock recorder for MockDB.
+type MockDBMockRecorder struct {
+	mock *MockDB
+}
+
+// NewMockDB creates a new mock instance.
+func NewMockDB(ctrl *gomock.Controller) *MockDB {
+	mock := &MockDB{ctrl: ctrl}
+	mock.recorder = &MockDBMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockDB) EXPECT() *MockDBMockRecorder {
+	return m.recorder
+}
+
+// GetLatestFileByPath mocks base method.
+func (m *MockDB) GetLatestFileByPath(ctx context.Context, path string) (*lib.File, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetLatestFileByPath", ctx, path)
+	ret0, _ := ret[0].(*lib.File)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetLatestFileByPath indicates an expected call of GetLatestFileByPath.
+func (mr *MockDBMockRecorder) GetLatestFileByPath(ctx, path any) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLatestFileByPath", reflect.TypeOf((*MockDB)(nil).GetLatestFileByPath), ctx, path)
+}