Skip to content

Commit

Permalink
feat: Setup SurrealDB (#110)
Browse files Browse the repository at this point in the history
* Create Configuration and Setup for surrealDB 
* Store in database resources and pages 
* Create integration tests and related documentation
  • Loading branch information
dricazenck authored Oct 4, 2024
1 parent 9cd63e0 commit 47d41ea
Show file tree
Hide file tree
Showing 40 changed files with 1,160 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
**/*.jfm
**/bin
**/charts
**/docker-compose*
docker/docker-compose.yml
**/compose.y*ml
**/Dockerfile*
**/node_modules
Expand Down
18 changes: 4 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,19 @@ jobs:
strategy:
matrix:
java-version: [ '21' ]



steps:
- name: Checkout code
uses: actions/checkout@v3
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE20: true
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true

- name: Set up JDK Set up JDK ${{ matrix.java-version }}
- name: Set up JDK ${{ matrix.java-version }}
uses: actions/setup-java@v3
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE20: true
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
with:
distribution: 'temurin'
java-version: ${{ matrix.java-version }}

- name: Cache Gradle packages
uses: actions/cache@v3
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE20: true
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
with:
path: |
~/.gradle/caches
Expand All @@ -49,14 +38,15 @@ jobs:
- name: Build and test
run: ./gradlew test jacocoTestReport
env:
DOCKER_HOST: "unix:///var/run/docker.sock"
TESTCONTAINERS_RYUK_DISABLED: "true"

- name: Pmd Check
run: ./gradlew pmdMain

- name: Jacoco Test Coverage Verification
run: ./gradlew jacocoTestCoverageVerification
env:
JAVA_HOME: ${{ steps.setup-java.outputs.java-home }}

- name: Upload code coverage report
if: success() || failure()
Expand Down
2 changes: 1 addition & 1 deletion .run/PlatformApplication.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<module name="wcc-backend.main" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.wcc.platform.*" />
<option name="PATTERN" value="com.wcc.platform.integrationtests.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* [Set-up wcc-backend project on local sonarQube instance](#set-up-wcc-backend-project-on-local-sonarqube-instance)
* [Perform SONAR ANALYSIS](#perform-sonar-analysis)
* [Deploy application](#deploy-application)
* [Deploy with docker compose](#deploy-with-docker-compose)
* [Deploy with docker](#deploy-with-docker)
* [Start docker with remote debug](#start-docker-with-remote-debug)
* [Start docker with mounted data volume](#start-docker-with-mounted-data-volume)
Expand Down Expand Up @@ -152,12 +153,21 @@ Once you've done that, restart the IDE.
./gradlew clean build
```

**Note**: Make sure you have docker daemon running locally to be able to run integration test, by
execute ``docker ps``

* Create Jar

```shell
./gradlew clean bootJar
```

* Start database

```shell
docker run --pull always --name surrealdb -p 8000:8000 -d surrealdb/surrealdb:latest start
```

* Start Spring Boot Application:

```shell
Expand Down Expand Up @@ -261,6 +271,22 @@ Generate token to replace in the project.

## Deploy application

### Deploy with docker compose

* build create jar: `./gradlew clean bootJar`
* Start docker compose

```shell
docker compose -f docker/docker-compose.yml up --build
```

* Stop docker compose

```shell
cd docker
docker compose down
```

### Deploy with docker

* build create jar: `./gradlew clean bootJar`
Expand Down
13 changes: 13 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.time.Duration

plugins {
java
pmd
Expand Down Expand Up @@ -26,23 +28,34 @@ repositories {
mavenCentral()
}

val testContainer = "1.19.0"

dependencies {

compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.surrealdb:surrealdb-driver:0.1.0")
implementation("org.java-websocket:Java-WebSocket:1.5.7")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.skyscreamer:jsonassert:1.5.3")

testImplementation("com.surrealdb:surrealdb-driver:0.1.0")
testImplementation("org.testcontainers:testcontainers:${testContainer}")
testImplementation("org.testcontainers:junit-jupiter:$testContainer")

testRuntimeOnly("org.junit.platform:junit-platform-launcher")
testCompileOnly("org.projectlombok:lombok")
testAnnotationProcessor("org.projectlombok:lombok")
}

tasks.withType<Test> {
useJUnitPlatform()
jvmArgs = listOf("-Xmx2048m")
timeout.set(Duration.ofMinutes(2))
}

tasks {
Expand Down
31 changes: 31 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: '3.7'

services:
surrealdb:
image: surrealdb/surrealdb:latest
container_name: surrealdb
ports:
- "8000:8000"
command: start --log trace --user root --pass root
networks:
- app-network

springboot-app:
build:
context: ..
dockerfile: Dockerfile
container_name: springboot-app
ports:
- "8080:8080"
- "5005:5005"
depends_on:
- surrealdb
environment:
- SURREALDB_USER=root
- SURREALDB_PASS=root
networks:
- app-network

networks:
app-network:
driver: bridge
2 changes: 2 additions & 0 deletions src/main/java/com/wcc/platform/PlatformApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import com.wcc.platform.configuration.ObjectMapperConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.annotation.Import;

/** Spring application service. */
@SpringBootApplication
@ConfigurationPropertiesScan
@Import(ObjectMapperConfig.class)
public class PlatformApplication {

Expand Down
37 changes: 37 additions & 0 deletions src/main/java/com/wcc/platform/configuration/DatabaseConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wcc.platform.configuration;

import com.surrealdb.connection.SurrealWebSocketConnection;
import com.surrealdb.driver.SyncSurrealDriver;
import com.wcc.platform.repository.surrealdb.SurrealDbConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** Database configuration to initialize Driver and connection. */
@Configuration
public class DatabaseConfig {

/** Create Sync driver connection for SurrealDB. */
@Bean
public SyncSurrealDriver getDriver(final SurrealDbConfig config) {
final var conn =
new SurrealWebSocketConnection(config.getHost(), config.getPort(), config.isTls());

conn.connect(config.getTimoutSeconds());

final var driver = new SyncSurrealDriver(conn);

driver.signIn(config.getUsername(), config.getPassword());

driver.use(config.getNamespace(), config.getDatabase());

return driver;
}

/** SurrealDB Config. */
@Bean
@ConfigurationProperties(prefix = "surrealdb")
public SurrealDbConfig getDbConfig() {
return new SurrealDbConfig();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.wcc.platform.domain.exceptions.ErrorDetails;
import com.wcc.platform.domain.exceptions.InvalidProgramTypeException;
import com.wcc.platform.domain.exceptions.PlatformInternalException;
import java.util.NoSuchElementException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand All @@ -19,7 +20,7 @@
public class GlobalExceptionHandler {

/** Receive ContentNotFoundException and return {@link HttpStatus#NOT_FOUND}. */
@ExceptionHandler(ContentNotFoundException.class)
@ExceptionHandler({ContentNotFoundException.class, NoSuchElementException.class})
@ResponseStatus(NOT_FOUND)
public ResponseEntity<ErrorDetails> handleNotFoundException(
final ContentNotFoundException ex, final WebRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
package com.wcc.platform.configuration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.surrealdb.driver.SyncSurrealDriver;
import com.wcc.platform.repository.MemberRepository;
import com.wcc.platform.repository.PageRepository;
import com.wcc.platform.repository.ResourceContentRepository;
import com.wcc.platform.repository.file.FileMemberRepository;
import com.wcc.platform.repository.surrealdb.SurrealDbPageRepository;
import com.wcc.platform.repository.surrealdb.SurrealDbResourceRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** RepositoryConfig. */
/** Repository Configurations to initialize respective implementation. */
@Configuration
public class RepositoryConfig {

/** Default repository of resources. */
@Bean
public ResourceContentRepository getResourceRepository(final SyncSurrealDriver driver) {
return new SurrealDbResourceRepository(driver);
}

@Bean
public PageRepository getPageRepository(final SyncSurrealDriver driver) {
return new SurrealDbPageRepository(driver);
}

/** Create FileMemberRepository bean. */
@Bean
public MemberRepository createFileRepository(
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/com/wcc/platform/controller/PlatformController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.wcc.platform.controller;

import com.wcc.platform.domain.platform.ResourceContent;
import com.wcc.platform.service.PlatformService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

/** Rest controller for event pages API. */
@RestController
@RequestMapping("/api/platform/v1/")
@Tag(name = "Platform General APIs")
public class PlatformController {

private final PlatformService service;

@Autowired
public PlatformController(final PlatformService service) {
this.service = service;
}

/** Put resources content for a program. */
@PostMapping("/resource")
@Operation(summary = "/api/v1/resource")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<ResourceContent> addResource(@RequestBody final ResourceContent resource) {
return ResponseEntity.ok(service.saveResourceContent(resource));
}

/** Get all resources content. */
@GetMapping("/resources")
@Operation(summary = "/api/v1/resources")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<Collection<ResourceContent>> getAllResources() {
return ResponseEntity.ok(service.getAllResources());
}

/** Get all resources content. */
@GetMapping("/resource")
@Operation(summary = "Get Resource by ID")
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<ResourceContent> getResourceById(@RequestParam final String id) {
return ResponseEntity.ok(service.getResourceById(id));
}

/** Delete resource content if exists. */
@DeleteMapping("/resource/{id}")
@Operation(summary = "Delete resource content if exists")
@ResponseStatus(HttpStatus.OK)
public void deleteResourceById(@PathVariable final String id) {
service.deleteById(id);
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/wcc/platform/domain/cms/pages/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.wcc.platform.domain.cms.attributes.Image;
import com.wcc.platform.domain.cms.attributes.LabelLink;
import java.util.List;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
Expand All @@ -19,6 +20,7 @@
@EqualsAndHashCode
@Builder
public class Page {
private UUID id;
private String title;
private String subtitle;
private String description;
Expand Down
Loading

0 comments on commit 47d41ea

Please sign in to comment.