Skip to content

Commit b5e4c46

Browse files
committed
My backend connecctivity to PostgreSQL and Redis keeps dropping despite first connecting and working for like a day, and apparently it's because of something Railway does internally where they rotate internal connection IPs and apparently this stuff in the .yml file will fix it.
1 parent b331a48 commit b5e4c46

File tree

6 files changed

+203
-123
lines changed

6 files changed

+203
-123
lines changed

springqpro-backend/src/main/java/com/springqprobackend/springqpro/controller/graphql/TaskGraphQLController.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import org.springframework.graphql.data.method.annotation.QueryMapping;
1818
import org.springframework.transaction.annotation.Transactional;
1919

20+
import java.util.Arrays;
2021
import java.util.List;
22+
import java.util.Map;
2123

2224
/* TaskGraphQLController.java
2325
--------------------------------------------------------------------------------------------------
@@ -123,6 +125,21 @@ public boolean deleteTask(@Argument String id, Authentication auth) {
123125
return taskService.deleteTask(id);
124126
}
125127

128+
/* 2025-12-04-NOTE: Adding a new method in the GraphQL Controller that exposes enums (useful for frontends
129+
so they can parse the acceptable enums defined in schema.graphqls and avoid hardcoding values). */
130+
@QueryMapping
131+
@PreAuthorize("isAuthenticated()")
132+
public Map<String, List<String>> taskEnums() {
133+
return Map.of(
134+
"taskTypes", Arrays.stream(TaskType.values())
135+
.map(Enum::name)
136+
.toList(),
137+
"taskStatuses", Arrays.stream(TaskStatus.values())
138+
.map(Enum::name)
139+
.toList()
140+
);
141+
}
142+
126143
// 2025-11-17-DEBUG: I can't remember why the thing below was added.
127144
/*@SchemaMapping(typeName = "Task", field = "payload")
128145
@PreAuthorize("hasAnyRole('ADMIN','SUPERVISOR')")

springqpro-backend/src/main/resources/application-prod.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@ spring:
44
username: ${PGUSER}
55
password: ${PGPASSWORD}
66

7+
hikari:
8+
maximum-pool-size: 5
9+
minimum-idle: 2
10+
idle-timeout: 10000 # 10s – close idle connections fairly quickly
11+
max-lifetime: 30000 # 30s – recycle before Railway drops them
12+
connection-timeout: 10000 # 10s – don't hang forever
13+
validation-timeout: 5000 # 5s – quick fail for bad connections
14+
leak-detection-threshold: 20000 # 20s – log if a connection is “stuck”
15+
716
jpa:
817
hibernate:
918
ddl-auto: update
1019
show-sql: false
20+
open-in-view: false
1121
properties:
1222
hibernate:
1323
format_sql: false
24+
jdbc:
25+
lob:
26+
non_contextual_creation: true
1427

1528
redis:
1629
host: ${REDISHOST}

springqpro-frontend/src/App.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { BrowserRouter, Routes, Route } from "react-router-dom";
1+
2+
3+
4+
import { BrowserRouter, Routes, Route, Navigate} from "react-router-dom";
5+
6+
7+
28
import { AuthProvider } from "./utility/auth/AuthContext";
39
import ProtectedRoute from "./utility/auth/ProtectedRoute";
410
import LoginPage from "./pages/LoginPage";
@@ -18,6 +24,12 @@ export default function App() {
1824
with the CMDE project where I auto-default the default URL to re-direct to /login or the dashboard
1925
depending on the browser has localStorage tokens or whatever it was that I did. */}
2026
{/*<Route path="/" element={<Navigate to="/Login" replace/>} />*/}
27+
28+
<Route path="/" element={<Navigate to="/login" replace/>} />
29+
30+
31+
32+
2133

2234
{/* LOGIN PAGE: */}
2335
<Route path="/login" element={<LoginPage />} />
@@ -43,7 +55,7 @@ export default function App() {
4355

4456
{/* Default root redirect: */}
4557
<Route path="*" element={<LoginPage />}/>
46-
\
58+
4759
</Routes>
4860
</AuthProvider>
4961
</BrowserRouter>

springqpro-frontend/src/api/api.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,25 @@ export async function logoutUser(refreshToken: string) {
5353
});
5454
return res.json();
5555
}
56+
57+
// Utility API calls:
58+
export async function getEnumLists(accessToken: string) {
59+
const query = `
60+
query {
61+
taskEnums {
62+
taskTypes
63+
taskStatuses
64+
}
65+
}
66+
`;
67+
const res = await fetch(`${API_BASE}/graphql`, {
68+
method: "POST",
69+
headers: {
70+
"Content-Type":"application/json",
71+
"Authorization":`Bearer ${accessToken}`
72+
},
73+
body: JSON.stringify({ query })
74+
});
75+
const json = await res.json();
76+
return json.data.taskEnums;
77+
}

springqpro-frontend/src/pages/LoginPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ export default function LoginPage() {
6363
const result = await loginUser(email, password);
6464
if (result.accessToken) {
6565
login(result.accessToken, result.refreshToken);
66+
// 2025-11-04-NOTE: If Login was a success both accessToken and refreshToken should be stored in browser localStorage:
67+
localStorage.setItem("access-token", result.accessToken);
68+
localStorage.setItem("refresh-token", result.refreshToken);
6669
navigate("/token-dashboard");
6770
} else {
6871
setServerError("Invalid email or password.");

0 commit comments

Comments
 (0)