Skip to content
This repository was archived by the owner on Sep 30, 2025. It is now read-only.

Comments

feat: Add SurrealDB schema files and dependencies#17

Merged
TN19N merged 1 commit intomainfrom
14-chapter-8
Sep 2, 2025
Merged

feat: Add SurrealDB schema files and dependencies#17
TN19N merged 1 commit intomainfrom
14-chapter-8

Conversation

@TN19N
Copy link
Owner

@TN19N TN19N commented Sep 2, 2025

This commit adds the SurrealDB schema files and dependencies to support database migrations and management.

It also includes: - Dependencies: axum-macros, include_dir - Files: .surrealdb, Cargo.lock and Cargo.toml changes. - Code: Implement confirm subscription

Summary by CodeRabbit

  • New Features

    • Automatic database migrations are bundled and applied on startup.
    • Subscription confirmation emails now include a cleaner, more reliable confirmation link.
  • Improvements

    • More robust error handling across startup and database operations for clearer failures instead of abrupt exits.
    • Health check enhanced for better runtime diagnostics.
  • Chores

    • Added SurrealDB project configuration.
    • Dependency updates to support framework macros and embedded assets.

This commit adds the SurrealDB schema files and dependencies to support
database migrations and management.

It also includes: - Dependencies: axum-macros, include_dir - Files:
.surrealdb, Cargo.lock and Cargo.toml changes. - Code: Implement confirm
subscription
@TN19N TN19N linked an issue Sep 2, 2025 that may be closed by this pull request
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 2, 2025

Walkthrough

Adds SurrealDB config file, updates dependencies (adds include_dir, axum macros), boxes SurrealDB errors, refactors health check error mapping, expands subscribe handler to use AppState and delegate confirmation to ModelManager, introduces ModelManager::confirm_subscriber, embeds and runs migrations at startup, and changes main to return Result instead of exiting.

Changes

Cohort / File(s) Summary
SurrealDB config
./.surrealdb
New config with [core] schema="full", path="./surrealdb".
Dependencies
Cargo.toml
axum enables "macros"; add include_dir "0.7.4"; reqwest features reflowed (no semantic change).
Error boxing & health check
src/errors.rs, src/handlers/health_check.rs
SurrealDb error variant now Boxsurrealdb::Error; health handler annotated with debug_handler(state = AppState); error mapping uses map_err(Box::new).
Subscription flow
src/handlers/subscription.rs
subscribe now extracts AppState (Config, EmailClient); confirmation uses mm.confirm_subscriber(token); refactors token generation and link construction via helper; updates email content.
Model manager & migrations
src/model.rs, surrealdb/*
Adds confirm_subscriber(token) -> Result<()>; standardizes DB error mapping via Box; embeds and loads migrations using include_dir and MigrationRunner::load_files.
Main entrypoint
src/main.rs
main returns Result<(), Error>; replaces exit-based handling with ? operator throughout startup.
Domain re-exports
src/domain/subscriber/mod.rs
Relocates pub use email::SubscriberEmail; within module (no API change).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Router as Axum Router
  participant SubH as subscribe Handler
  participant MM as ModelManager
  participant EC as EmailClient
  participant DB as SurrealDB

  User->>Router: POST /subscriptions (form)
  Router->>SubH: Extract State(mm, config, email_client) + Form
  SubH->>MM: create_subscriber(form)
  MM->>DB: INSERT subscription (pending)
  DB-->>MM: ok / error (boxed)
  alt insert ok
    SubH->>EC: send_confirmation_email(get_confirmation_link(config, token))
    EC-->>SubH: ok
    SubH-->>Router: 200 OK
  else insert/email error
    SubH-->>Router: error (propagated)
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant Router as Axum Router
  participant ConfH as confirm Handler
  participant MM as ModelManager
  participant DB as SurrealDB

  User->>Router: GET /subscriptions/confirm?token=...
  Router->>ConfH: Extract State(mm)
  ConfH->>MM: confirm_subscriber(token)
  MM->>DB: UPDATE subscriptions SET status=CONFIRMED WHERE ...
  DB-->>MM: ok / error (boxed)
  MM-->>ConfH: Result
  ConfH-->>Router: 200 OK or error
Loading
sequenceDiagram
  autonumber
  participant Main as main()
  participant MM as ModelManager
  participant FS as Embedded Migrations
  participant DB as SurrealDB

  Main->>MM: connect()
  MM->>DB: connect/signin (errors boxed)
  MM->>FS: load migrations (include_dir)
  MM->>DB: apply migrations .up()
  DB-->>MM: ok / error
  MM-->>Main: Result
  Main-->>Main: use ? to propagate
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: finish chapter 7 #12: Overlaps on SurrealDB migration loading, confirmation flow, and error boxing in model and handlers.
  • feat/chapter 6 #9: Related changes in subscriber domain, model creation logic, and subscription handlers.

Suggested labels

enhancement

Poem

I twitch my nose at freshly brewed DB tea,
Migrations hop in, bundled merrily.
Tokens twirl, confirmations chime,
Boxed errors snug—everything’s fine.
With axum macros I take the lane—
Hippity start-up, no exit, just “?” again. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 14-chapter-8

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot added the enhancement New feature or request label Sep 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
Cargo.toml (1)

27-29: Gate SurrealDB storage backends via Cargo features

kv-mem is great for tests/dev but not for prod. Suggest feature flags to switch backends without touching code.

 [dependencies]
-surrealdb = { version = "2.3.7", features = ["kv-mem"] }
+surrealdb = { version = "2.3.7", default-features = false }
 
+[features]
+default = ["db-mem"]
+# In-memory (dev/test)
+db-mem = ["surrealdb/kv-mem"]
+# Example alternative backends you can enable in prod builds:
+# db-rocks = ["surrealdb/kv-rocksdb"]
+# db-tikv  = ["surrealdb/kv-tikv"]

If you adopt this, ensure CI builds pass with at least --features db-mem.

src/errors.rs (1)

31-38: Polish log messages; keep semantics the same

Minor wording fixes for clarity; retains status behavior.

-                tracing::info!("Bad request: - {self:?}");
+                tracing::info!("Bad Request - {self:?}");
@@
-                tracing::error!("Internal Server: - {self:?}");
+                tracing::error!("Internal Server Error - {self:?}");
src/model.rs (3)

86-93: Avoid string interpolation for credentials in DDL

Interpolating username/password directly into DEFINE USER is fragile (quoting) and risky if config ever becomes untrusted. Prefer parameters if Surreal supports them for DDL, or at least ensure strict validation/sanitization of username.

If params aren’t supported in DDL, validate config.username against ^[A-Za-z0-9_]+$ before executing.


107-113: Add migration locking to prevent concurrent runners

If this service can start multiple instances, guard migrations with a lock key to avoid race conditions. Many migration runners expose a lock key API.


109-113: Stabilize migrations dir reference and correct path
Verified the migrations folder is named surrealdb/ (no leading dot). Define a 'static Dir and reference it to avoid holding a temporary reference across .up().await:

-use include_dir::include_dir;
+use include_dir::{include_dir, Dir};
+
+static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/surrealdb");
@@
-        .load_files(&include_dir!("$CARGO_MANIFEST_DIR/surrealdb"))
+        .load_files(&MIGRATIONS_DIR)
src/handlers/subscription.rs (1)

31-35: Minor observability tweak

Consider logging a compact event after DB write and after email send (without PII/token). Helps diagnose issues without leaking secrets.

Also applies to: 62-85

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 702e021 and 2f081ea.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • .surrealdb (1 hunks)
  • Cargo.toml (2 hunks)
  • src/domain/subscriber/mod.rs (1 hunks)
  • src/errors.rs (1 hunks)
  • src/handlers/health_check.rs (1 hunks)
  • src/handlers/subscription.rs (4 hunks)
  • src/main.rs (2 hunks)
  • src/model.rs (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-28T13:50:40.460Z
Learnt from: TN19N
PR: TN19N/subscriptions#9
File: src/domain/subscriber/email.rs:18-19
Timestamp: 2025-08-28T13:50:40.460Z
Learning: For the SubscriberEmail validation in src/domain/subscriber/email.rs, the user TN19N prefers to include the actual email value in ValidationError messages for debugging purposes, accepting the PII exposure trade-off in favor of detailed error information returned with 400 HTTP status.

Applied to files:

  • src/domain/subscriber/mod.rs
🧬 Code graph analysis (5)
src/domain/subscriber/mod.rs (2)
src/email_client.rs (1)
  • email (201-204)
src/domain/subscriber/email.rs (4)
  • SubscriberEmail (6-6)
  • tests (27-65)
  • AsRef (8-12)
  • as_ref (9-11)
src/handlers/health_check.rs (3)
src/state.rs (4)
  • new (17-23)
  • AppState (10-14)
  • FromRef (26-30)
  • FromRef (32-36)
tests/api/health_check.rs (1)
  • health_works (4-16)
src/startup.rs (1)
  • init (20-43)
src/handlers/subscription.rs (2)
src/email_client.rs (2)
  • email_client (207-215)
  • EmailClient (25-62)
src/state.rs (1)
  • AppState (10-14)
src/main.rs (3)
src/config.rs (1)
  • load (36-41)
src/startup.rs (1)
  • init (20-43)
src/state.rs (1)
  • AppState (16-24)
src/model.rs (4)
src/state.rs (1)
  • new (17-23)
tests/api/helpers.rs (1)
  • new (24-51)
tests/api/subscriptions_confirm.rs (2)
  • QueryResult (52-56)
  • confirmation_works (24-75)
tests/api/subscriptions.rs (2)
  • subscribe_works (10-48)
  • subscribe_returns_a_200_for_valid_form_data (150-191)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: check
🔇 Additional comments (10)
src/domain/subscriber/mod.rs (1)

5-5: LGTM: Re-export reorder is non-breaking.

Public API unchanged; moving pub use email::SubscriberEmail; below the import is fine.

Cargo.toml (3)

17-17: Enabling axum macros is correct for #[axum::debug_handler]

This aligns with the handler attribute usage. LGTM.


20-23: No functional change in reqwest features

Purely formatting; nothing to flag.


40-40: include_dir addition: OK

Matches the embedded migrations approach.

src/handlers/health_check.rs (1)

7-7: Good use of #[axum::debug_handler] with AppState

This helps catch extractor/state issues at compile time. LGTM.

src/main.rs (1)

6-6: main returning Result is a solid improvement

Error propagation via ? keeps startup code clean. LGTM.

src/model.rs (2)

48-50: Good: transaction + .check() ensures write errors surface

The transaction around token + subscription creation plus .check() is solid. This should fail fast on constraint errors once you add schema.


81-84: Consistent boxed error mapping looks good

Uniform .map_err(Box::new)? across connect, mem-setup, and signin keeps error typing consistent with your crate’s Result.

Also applies to: 94-96, 104-106

src/handlers/subscription.rs (2)

87-92: Confirmation link builder looks correct

Url::join + set_query avoids manual string concat and handles base URL slashes.


55-57: No changes needed: rand::rng() and rand::distr::Alphanumeric are correct for rand 0.9.2
Your Cargo.toml pins rand at 0.9.2, where top-level thread_rng() was renamed to rng() (with thread_rng() kept as a deprecated alias) and the distributions module was renamed to distr (docs.rs)

@TN19N TN19N self-assigned this Sep 2, 2025
@TN19N TN19N merged commit 430c598 into main Sep 2, 2025
2 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chapter 8

1 participant