Skip to content

Commit ab29b71

Browse files
committed
Persistence init
1 parent 4aa46cc commit ab29b71

9 files changed

Lines changed: 143 additions & 2272 deletions

File tree

docker-compose.yml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ services:
1212
- POSTGRES_DB=flicker
1313

1414

15-
mcp-gateway:
16-
image: docker/agents_gateway:v2
17-
ports:
18-
- 9012:9011
19-
volumes:
20-
- "/var/run/docker.sock:/var/run/docker.sock"
21-
- "/run/host-services/backend.sock:/run/host-services/backend.sock"
22-
command:
23-
- --verbose
24-
- --transport=sse
25-
- --secrets=/run/secrets/mcp_secret
26-
- --servers=brave,wikipedia-mcp,puppeteer,github,openbnb-airbnb,google-maps
27-
- --tools=openbnb-airbnb:*
28-
- --tools=brave_web_search
29-
- --tools=wikipedia-mcp:*
30-
- --tools=puppeteer:*
31-
- --tools=google-maps:*
32-
- --port=9011
33-
secrets:
34-
- mcp_secret
15+
# mcp-gateway:
16+
# image: docker/agents_gateway:v2
17+
# ports:
18+
# - 9012:9011
19+
# volumes:
20+
# - "/var/run/docker.sock:/var/run/docker.sock"
21+
# - "/run/host-services/backend.sock:/run/host-services/backend.sock"
22+
# command:
23+
# - --verbose
24+
# - --transport=sse
25+
# - --secrets=/run/secrets/mcp_secret
26+
# - --servers=brave,wikipedia-mcp,puppeteer,github,openbnb-airbnb,google-maps
27+
# - --tools=openbnb-airbnb:*
28+
# - --tools=brave_web_search
29+
# - --tools=wikipedia-mcp:*
30+
# - --tools=puppeteer:*
31+
# - --tools=google-maps:*
32+
# - --port=9011
33+
# secrets:
34+
# - mcp_secret
3535

3636
secrets:
3737
mcp_secret:

src/main/kotlin/com/embabel/agent/web/security/EmbabelOAuth2UserService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import org.springframework.stereotype.Service
1313

1414
@Service
1515
class EmbabelOAuth2UserService(
16-
private val userService: UserService<User>,
16+
private val userService: UserService<*>,
1717
) : DefaultOAuth2UserService() {
1818

1919
override fun loadUser(userRequest: OAuth2UserRequest): OAuth2User {

src/main/kotlin/com/embabel/movie/FlickerApplication.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.springframework.boot.runApplication
2626
@ConfigurationPropertiesScan
2727
@EnableAgents(
2828
loggingTheme = LoggingThemes.SEVERANCE,
29-
mcpServers = [McpServers.DOCKER, McpServers.DOCKER_DESKTOP],
29+
mcpServers = [McpServers.DOCKER],
3030
)
3131
class FlickerApplication
3232

src/main/kotlin/com/embabel/movie/domain/MovieService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class MovieService(
8282
fun rate(movieBuff: MovieBuff, title: String, rating: OneThroughTen) {
8383
val movie = omdbClient.getMovieByTitle(title)
8484
if (movie == null) {
85-
logger.info("Movie not found for title{}", title)
85+
logger.info("Movie not found for title {}", title)
8686
return
8787
}
8888
rate(movieBuff, movie, rating)

src/main/kotlin/com/embabel/movie/populate/populator.kt

Lines changed: 68 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,59 +16,72 @@
1616
package com.embabel.movie.populate
1717

1818
import com.embabel.common.util.RandomFromFileMessageGenerator
19-
import com.embabel.movie.domain.MovieBuff
20-
import com.embabel.movie.domain.MovieService
21-
import com.embabel.movie.domain.StreamingService
22-
import com.embabel.movie.domain.StreamingServiceRepository
19+
import com.embabel.movie.domain.*
20+
import org.slf4j.LoggerFactory
2321
import org.springframework.boot.ApplicationArguments
2422
import org.springframework.boot.ApplicationRunner
2523
import org.springframework.stereotype.Component
24+
import org.springframework.stereotype.Service
2625
import org.springframework.transaction.annotation.Transactional
2726

28-
@Component
29-
class StartupDataInitializer(
27+
@Service
28+
class DataPopulatorService(
3029
private val movieService: MovieService,
30+
private val movieBuffRepository: MovieBuffRepository,
3131
private val streamingServiceRepository: StreamingServiceRepository,
32-
) : ApplicationRunner {
32+
) {
33+
private val logger = LoggerFactory.getLogger(DataPopulatorService::class.java)
3334

3435
@Transactional
35-
override fun run(args: ApplicationArguments?) {
36-
// Skip if data already exists
37-
if (streamingServiceRepository.count() > 0) {
38-
return
39-
}
36+
fun populate() {
37+
try {
38+
logger.info(
39+
"{} streaming services, {} movie buffs found in database.",
40+
streamingServiceRepository.count(),
41+
movieBuffRepository.count(),
42+
)
43+
// Skip if data already exists
44+
if (streamingServiceRepository.count() > 0 || movieBuffRepository.count() > 0) {
45+
return
46+
}
4047

41-
val netflix = StreamingService("Netflix", "https://www.netflix.com")
42-
streamingServiceRepository.save(netflix)
43-
val stan = StreamingService("Stan", "https://www.stan.com.au")
44-
streamingServiceRepository.save(stan)
45-
val disneyPlus = StreamingService("Disney+", "https://www.disneyplus.com")
46-
streamingServiceRepository.save(disneyPlus)
48+
logger.info("Populating initial data...")
4749

48-
val name = "Rod"
49-
if (movieService.findMovieBuffByName(name) == null) {
50-
val rod = MovieBuff(
51-
username = "Rod",
52-
displayName = "Rod Johnson",
53-
email = "johnsonroda@gmail.com",
54-
hobbies = listOf("Travel", "Skiing", "Chess", "Hiking", "Reading"),
55-
countryCode = "au",
56-
about = """
57-
Rod is an Australian man who has a PhD in Musicology and
58-
has a career as a software engineer, author and tech entrepreneur.
59-
He is widely traveled and has lived in California and the UK
60-
before returning to Sydney.
61-
""".trimIndent(),
62-
streamingServices = mutableListOf(netflix, stan, disneyPlus),
63-
movieLikes = "Complex plots, film noir",
64-
movieDislikes = "Predictable endings, formulaic blockbusters, anime",
65-
)
66-
loadRatings(rod, "movie/rod_ratings.tsv")
67-
movieService.save(rod)
50+
val netflix = StreamingService("Netflix", "https://www.netflix.com")
51+
streamingServiceRepository.save(netflix)
52+
val stan = StreamingService("Stan", "https://www.stan.com.au")
53+
streamingServiceRepository.save(stan)
54+
val disneyPlus = StreamingService("Disney+", "https://www.disneyplus.com")
55+
streamingServiceRepository.save(disneyPlus)
56+
57+
val name = "Rod"
58+
if (movieService.findMovieBuffByName(name) == null) {
59+
val rod = MovieBuff(
60+
username = "Rod",
61+
displayName = "Rod Johnson",
62+
email = "johnsonroda@gmail.com",
63+
hobbies = listOf("Travel", "Skiing", "Chess", "Hiking", "Reading"),
64+
countryCode = "au",
65+
about = """
66+
Rod is an Australian man who has a PhD in Musicology and
67+
has a career as a software engineer, author and tech entrepreneur.
68+
He is widely traveled and has lived in California and the UK
69+
before returning to Sydney.
70+
""".trimIndent(),
71+
streamingServices = mutableListOf(netflix, stan, disneyPlus),
72+
movieLikes = "Complex plots, film noir",
73+
movieDislikes = "Predictable endings, formulaic blockbusters, anime",
74+
)
75+
loadRatings(rod, "movie/rod_ratings.tsv")
76+
movieService.save(rod)
77+
}
78+
logger.info("Data population completed successfully")
79+
} catch (e: Exception) {
80+
logger.error("Data population failed - transaction will rollback", e)
81+
throw e
6882
}
6983
}
7084

71-
7285
fun loadRatings(movieBuff: MovieBuff, tsv: String) {
7386
addRatings(
7487
movieBuff,
@@ -77,7 +90,6 @@ class StartupDataInitializer(
7790
)
7891
}
7992

80-
8193
fun addRatings(
8294
movieBuff: MovieBuff,
8395
inputs: List<String>,
@@ -90,7 +102,21 @@ class StartupDataInitializer(
90102
// Last element is the rating, everything else is the title
91103
val rating = parts.last().toInt()
92104
val title = parts.dropLast(1).joinToString(" ")
93-
movieService.rate(movieBuff, title, rating)
105+
try {
106+
movieService.rate(movieBuff, title, rating)
107+
} catch (e: Exception) {
108+
logger.warn("Failed to rate movie '{}' with rating {}: {}", title, rating, e.message)
109+
}
94110
}
95111
}
96-
}
112+
}
113+
114+
@Component
115+
class StartupDataInitializer(
116+
private val dataPopulatorService: DataPopulatorService,
117+
) : ApplicationRunner {
118+
119+
override fun run(args: ApplicationArguments?) {
120+
dataPopulatorService.populate()
121+
}
122+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
spring:
2+
3+
ai:
4+
mcp:
5+
client:
6+
enabled: true
7+
name: embabel
8+
version: 1.0.0
9+
request-timeout: 30s
10+
type: SYNC
11+
12+
stdio:
13+
connections:
14+
brave-search-mcp:
15+
command: docker
16+
args:
17+
- run
18+
- -i
19+
- --rm
20+
- -e
21+
- BRAVE_MCP_TRANSPORT
22+
- -e
23+
- BRAVE_API_KEY
24+
- mcp/brave-search
25+
env:
26+
BRAVE_MCP_TRANSPORT: "stdio"
27+
BRAVE_API_KEY: ${BRAVE_API_KEY}
28+
fetch-mcp:
29+
command: docker
30+
args:
31+
- run
32+
- -i
33+
- --rm
34+
- mcp/fetch
35+
puppeteer-mcp:
36+
command: docker
37+
args:
38+
- run
39+
- -i
40+
- --rm
41+
- -e
42+
- DOCKER_CONTAINER
43+
- mcp/puppeteer
44+
env:
45+
DOCKER_CONTAINER: true
46+
# wikipedia-mcp:
47+
# command: docker
48+
# args:
49+
# - run
50+
# - -i
51+
# - --rm
52+
# - mcp/wikipedia-mcp
Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +0,0 @@
1-
spring:
2-
3-
ai:
4-
mcp:
5-
client:
6-
enabled: true
7-
name: embabel
8-
version: 1.0.0
9-
request-timeout: 30s
10-
type: SYNC
11-
12-
sse:
13-
connections:
14-
local:
15-
# Allow the DOCKER_MCP environment variable to override the default URL
16-
url: ${DOCKER_MCP:http://localhost:9012}
17-
18-

src/main/resources/application.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,6 @@ spring:
5858
hibernate:
5959
ddl-auto: update
6060
properties:
61-
jakarta:
62-
persistence:
63-
schema-generation:
64-
create-source: metadata
65-
scripts:
66-
action: create
67-
create-target: src/main/resources/schema.sql
6861
hibernate:
6962
default_schema: flicker
7063
hbm2ddl:

0 commit comments

Comments
 (0)