Skip to content

Conversation

@vim89
Copy link

@vim89 vim89 commented Nov 9, 2025

database-configuration & transaction management

  • Add Scala 3.7+ database transaction support with @cask.database.transactional decorator.
  • Uses reflection-based implementation with ClassTag for type safety, enabling cross-compilation across Scala 2.12, 2.13, 3.3.4, and 3.7.3.
  • Automatically commits on success and rolls back on exceptions or HTTP 4xx/5xx responses.

application configuration

With com.typesafe:config and HOCON

  • Functional config loader with Either error handling and ADT error types
  • Environment profile support (dev/test/prod via CASK_ENV)
  • Type-safe accessors for string/int/boolean/long/double with optional variants
  • Config example showing usage and environment overrides
  • Updated todoDb example to use config for database path and initial data
  • Unit Tests

Issue #181 #183

vim89 added 12 commits November 9, 2025 16:24
Implements Phase 0 database configuration proposal with auto-configuration
and automatic transaction management for Scala 3.7+.

Core features:
- Auto-configured DbClient from application.conf
- @cask.transactional decorator with using syntax
- Smart rollback on exceptions and HTTP 4xx/5xx responses
- SimpleTable support via scalasql-namedtuples

Implementation:
- cask.database.DatabaseConfig: Auto-configuration from application.conf
- cask.database.transactional: Transaction decorator with using clause
- cask.database package: Type aliases and documentation

Dependencies (Scala 3.7+ only):
- ScalaSql 0.2.3 with scalasql-namedtuples
- Typesafe Config for application.conf loading
- Added conditional ScalaSql dependency for Scala 3.7+ builds

- Implemented @cask.database.transactional decorator for transaction management

- Uses reflection to avoid compile-time dependency on ScalaSql for older Scala versions

- Auto-commits on success, rolls back on exceptions or HTTP 4xx/5xx responses

- Updated todoDb examples to use scalasql.simple API with SimpleTable pattern

- Cross-compilation support for Scala 2.12, 2.13, 3.3.4, and 3.7.3
- Added ClassTag context bound to preserve type information at runtime

- Validates type matches at runtime to catch misuse early

- Documents type safety approach using Scala's reflection mechanism

- Prevents type erasure issues while maintaining cross-compilation compatibility
feat: database configuration & transaction management
Issue com-lihaoyi#181
feat: database-configuration & transaction management
- Functional config loader with Either-based error handling and ADT error types
- Environment profile support (dev/test/prod) via CASK_ENV variable
- Type-safe accessors for string/int/boolean/long/double with optional variants
- Config example showing HOCON usage and environment overrides
- Updated todoDb example to use config for database path and initial data
- Comprehensive test coverage with 7 tests for all config features
- Cross-compiles across Scala 2.12, 2.13, 3.3.4, 3.7.3
- Functional config loader with Either-based error handling and ADT error types
- Environment profile support (dev/test/prod) via CASK_ENV variable
- Type-safe accessors for string/int/boolean/long/double with optional variants
- Config example showing HOCON usage and environment overrides
- Updated todoDb example to use config for database path and initial data
- Comprehensive test coverage with 7 tests for all config features
- Cross-compiles across Scala 2.12, 2.13, 3.3.4, 3.7.3
@vim89 vim89 changed the title feat: database-configuration & transaction management feat: database-configuration & transaction management + application.conf Nov 9, 2025
…lication-config

feat: application config
* }
* }}}
*/
class transactional[T <: AnyRef : ClassTag](using dbClient: T) extends RawDecorator {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop the class tag and just hardcode the compile-time dependency on ScalaSql. If anyone wants an alternative database library, they can define their own decorator to do so, no need to try and make this one generic

Comment on lines +36 to +38
/** Lazily loaded configuration */
private lazy val loader: InternalConfig.Loader =
InternalConfig.Loader.loadOrThrow()
Copy link
Member

@lihaoyi lihaoyi Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the scope of this config? Is it process-scoped, thread-local, or something else?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configuration is process-scoped and loaded once lazily when first accessed. The config. is immutable after loading; changes to config files require app restart

Added clear documentation

@@ -1,40 +1,31 @@
package app
import scalasql.DbApi.Txn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason you are removing this import? Seems like it makes all the code in the file a lot more verbose needing to spell out scalasql.core.DbApi.Txn over and over

@lihaoyi
Copy link
Member

lihaoyi commented Nov 10, 2025

Let's split out the database integration and config-management integration into separate PRs

@vim89 vim89 marked this pull request as draft November 18, 2025 02:17
@vim89
Copy link
Author

vim89 commented Nov 18, 2025

This PR has been split into two separate PRs as requested:

Both PRs address the review feedback:

  • Config scope is now documented as process-scoped lazy val
  • Database decorator no longer uses ClassTag/reflection
  • ScalaSql dependency is hardcoded at compile-time
  • DbApi.Txn import restored in examples

Closing this PR in favor of the focused PRs.

@vim89 vim89 closed this Nov 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants