starke
03/27/2024, 1:25 AMkotlin-inject
to supply the dependencies.
I’m starting to think that using a DI library may not be super compatible with the way that ResourceScope
works, because I can’t really figure out a good way to provide my database dependencies as a Resource
when using kotlin-inject
to provide the dependency instances.
Does anyone have any guidance on whether it makes sense to use something like kotlin-inject
alongside the arrow Resource
management stuff? Any insight would be helpful! Thanks 🙂Riccardo Cardin
03/27/2024, 6:11 AMsimon.vergauwen
03/27/2024, 8:28 AMResourceScope
doesn't mix with DI since they overlap in features like @Riccardo Cardin mentioned.
If you're interested in Resource, here is 2 talks of me talking about it.
• https://nomisrev.github.io/grateful-shutdown-with-structured-concurrency/
• https://nomisrev.github.io/graceful-resource-handling-using-structured-concurrency-in-kotlin/
And an example repo, https://github.com/nomisRev/ktor-arrow-examplesimon.vergauwen
03/27/2024, 8:28 AMstarke
03/27/2024, 12:13 PMstarke
04/10/2024, 10:19 PMsimon.vergauwen
04/11/2024, 5:56 AMstarke
04/12/2024, 7:17 PMDependencies
file/class 🤔
I don’t have a lot of dependencies yet, but am considering doing something like this to modularize the DI a bit more.
class Dependencies(
val healthChecks: HealthCheckRegistry,
val persistence: PersistenceModule,
val services: ServicesModule,
val externalClients: FooModule,
)
class PersistenceModule(
val dataSource: HikariDataSource,
val database: Database,
)
class ServicesModule(
val fooService: EventsService,
val barService: GroupsService,
)
class FooModule(
val bar: Bar,
)
Maybe overkill though? I may just be stuck in a dagger-style DI mindset 😆
This will be my first project that implements DI without a framework, so I’m just looking for whatever guidance y’all may have. Thanks!starke
04/12/2024, 7:19 PMPersistenceModule
in this case)
suspend fun ResourceScope.newPersistenceModule(
env: Environment.DataSource,
): Dependencies.PersistenceModule {
val hikari = newHikariDataSource(env)
return Dependencies.PersistenceModule(
dataSource = hikari,
database = newDatabase(hikari)
)
}
private suspend fun ResourceScope.newHikariDataSource(
env: Environment.DataSource,
): HikariDataSource = autoCloseable {
HikariDataSource(
HikariConfig().apply {
jdbcUrl = env.url
username = env.username
password = env.password
driverClassName = env.driverClassName
}
)
}
private suspend fun ResourceScope.newDatabase(
dataSource: DataSource,
adapters: DatabaseTypeAdapters = DatabaseTypeAdapters(),
): Database {
performMigrations(dataSource)
val jdbcDriver = closeable { dataSource.asJdbcDriver() }
return Database(
driver = jdbcDriver,
fooAdapter = adapters.foo,
barAdapter = adapters.bar,
)
}
private fun performMigrations(dataSource: DataSource) {
val migrationFilesLocation = Paths
.get("server", "build", "resources", "migrations")
.toAbsolutePath().toString()
Flyway.configure()
.dataSource(dataSource)
.locations("filesystem:$migrationFilesLocation")
.validateMigrationNaming(true)
.validateOnMigrate(true)
.load()
.migrate()
}
simon.vergauwen
04/12/2024, 7:20 PMsimon.vergauwen
04/12/2024, 7:20 PMstarke
04/12/2024, 7:21 PMsimon.vergauwen
04/12/2024, 7:21 PMstarke
04/12/2024, 7:21 PMRiccardo Cardin
04/13/2024, 6:37 AM