Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Async Support #276

Merged
merged 90 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
159d715
dummy commit for discussion
aDogCalledSpot Dec 25, 2022
c132064
wip making async
aDogCalledSpot Dec 26, 2022
e340746
more wip on postgres
aDogCalledSpot Jan 8, 2023
fa490b8
wip
aDogCalledSpot Jan 8, 2023
5e9c861
Missing feature cfg on a use statement
Electron100 Jan 15, 2023
e59707b
Fix methods which do not need to be async
Electron100 Jan 15, 2023
053f29d
Support async in Many
Electron100 Jan 15, 2023
63dbd31
Update Cargo.lock
Electron100 Jan 15, 2023
9900a9b
Apply rustfmt
Electron100 Jan 15, 2023
0c59454
DataResult::query should not be async
Electron100 Jan 16, 2023
2b6c1d6
more wip
aDogCalledSpot Jan 23, 2023
6471f0c
Merge branch 'feat-async' of https://github.com/aDogCalledSpot/butane…
Electron100 Feb 4, 2023
44f5266
Fixups
Electron100 Feb 5, 2023
7900468
compiles
aDogCalledSpot Feb 12, 2023
f297cb6
Merge branch 'feat-async' of https://github.com/aDogCalledSpot/butane…
Electron100 May 7, 2023
deed29b
Update versions
Electron100 May 7, 2023
29c8da9
Work on lifetimes
Electron100 May 10, 2023
5a0fbab
Work on macros
Electron100 May 20, 2023
546fff6
Merge branch 'master' into async-wip
Electron100 May 20, 2023
66c7785
Fix some merge issues
Electron100 May 20, 2023
b893dd7
Delete now explicit
Electron100 May 20, 2023
b876e22
Lots of awawits
Electron100 May 22, 2023
aa5b100
Merge branch 'master' into async-wip
Electron100 May 29, 2023
f3b7193
Test passing, sqlite disabled
Electron100 May 29, 2023
917a41a
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Jul 5, 2023
36f8574
pg: remove unused conn handle
Electron100 Jul 6, 2023
b4ea4a0
Introduce maybe-async-cfg
Electron100 Jul 8, 2023
357da6c
Add sync option for mod db
Electron100 Jul 11, 2023
d7305c3
Sync-to-Async Adapter mostly working
Electron100 Jul 28, 2023
339b59a
Sqlite re-enabled in tests, tests passing
Electron100 Aug 2, 2023
0049a42
Clippy fixes
Electron100 Aug 2, 2023
753edaf
Re-enable cli test test_migrate_and_query
Electron100 Aug 2, 2023
6ac8167
Re-enable cargo check with sqlite
Electron100 Aug 3, 2023
aaa4301
Re-enable sqlite in butane cli
Electron100 Aug 3, 2023
7e235c7
Re-enable sqlite in example
Electron100 Aug 3, 2023
6a2ae44
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Aug 5, 2023
89b9b40
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Mar 17, 2024
5e99cc2
Allow `Query` and `Many` to operate either sync or async
Electron100 Apr 7, 2024
5c33ee6
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Apr 8, 2024
52eaffb
Add async_checklist.md
Electron100 Apr 8, 2024
aa8e59d
better rendering of checklist
Electron100 Apr 8, 2024
c7805cf
Allow choice of sync or async for DataObject load/save methods
Electron100 Apr 9, 2024
ff8b0c9
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Jul 13, 2024
e6314e7
Migrations are now sync instead of async
Electron100 Jul 15, 2024
13cdcd7
Add getting_started_async
Electron100 Jul 15, 2024
5a87d90
Progress
Electron100 Jul 15, 2024
ceeed30
CLI sync
Electron100 Jul 24, 2024
b1c4516
Single Backend trait
Electron100 Jul 24, 2024
c9ce3e9
Merge remote-tracking branch 'origin/async-wip' into async/sync_migra…
Electron100 Jul 25, 2024
9fa72df
Tests almost all passing
Electron100 Jul 26, 2024
c581083
Last test passing (I think)
Electron100 Jul 26, 2024
1d157b3
Fix doctest
Electron100 Jul 26, 2024
cbad41a
Fix typo and fake test
Electron100 Jul 27, 2024
f3bd177
Re-enable r2d2 feature
Electron100 Jul 27, 2024
ffe490f
Changed approach to naming. Sync first, async gets a suffix
Electron100 Aug 29, 2024
ce6ea87
Update checklist
Electron100 Aug 29, 2024
a811e2f
Support sync in `find` and `ForeignKey` again
Electron100 Sep 6, 2024
bf4b171
Fix a doctest
Electron100 Sep 6, 2024
d187e02
Standard once cell handling between fkey and many
Electron100 Sep 6, 2024
6cb1846
Unconditionally implement Clone for Query
Electron100 Sep 6, 2024
79a4e73
find_async in example
Electron100 Sep 6, 2024
2ea6e5e
Switch to butane_test macro and run tests for both sync and async
Electron100 Oct 11, 2024
780cedd
Update checklist
Electron100 Oct 11, 2024
76b2e55
async_trait: add back Send bound
Electron100 Oct 16, 2024
b31e3db
Pluralize, Ops instead of Op
Electron100 Oct 20, 2024
8c8414f
Remove tokio dependency from ForeignKey and Many
Electron100 Oct 20, 2024
5dd33b4
Merge branch 'async-wip' of github.com:Electron100/butane into async-wip
Electron100 Oct 20, 2024
f5cf8d9
Minor misc. work on async todos
Electron100 Oct 26, 2024
7212248
Add README notes on breaking changes
Electron100 Oct 26, 2024
4225c42
Another readme update
Electron100 Oct 26, 2024
10f7caa
Merge remote-tracking branch 'origin/master' into async-wip
Electron100 Oct 26, 2024
708280a
fix editorconfig-checker issues
jayvdb Oct 26, 2024
74cfdd4
Address new lints
Electron100 Oct 27, 2024
3fb8502
Use github version of maybe-async-cfg to avoid proc-macro-error
Electron100 Oct 27, 2024
6853af1
Fix line length in Cargo.toml
Electron100 Oct 27, 2024
32370ef
Self-review part 1
Electron100 Oct 27, 2024
72ccfc5
Fix error with tokio::test not found
Electron100 Oct 27, 2024
e1b6255
Same fix for main lib
Electron100 Oct 27, 2024
9ac8ee2
Fix Cargo.toml again
Electron100 Oct 27, 2024
900cd65
Fix a DeepSource warning
Electron100 Oct 27, 2024
1402544
getting_started_async to workspace
Electron100 Oct 27, 2024
6770f4f
Fully remove tokio from CLI
Electron100 Oct 27, 2024
2bbf1ef
Fix getting_started_async
Electron100 Oct 27, 2024
d859b51
Fix getting_started_async tests
Electron100 Oct 27, 2024
f58d59e
fix newtype dev-deps
jayvdb Oct 27, 2024
0009f58
Non-functional changes; docs, comments, alpha sorting
jayvdb Oct 27, 2024
ae9dbc0
undo some unnecessary changes to migration-tests
jayvdb Oct 27, 2024
a3715d7
rv changes to connect()
jayvdb Oct 27, 2024
c5d064f
tidy
jayvdb Oct 27, 2024
ece48ee
CR comments and continued self-CR
Electron100 Oct 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 216 additions & 33 deletions Cargo.lock

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ members = [
"butane_codegen",
"butane_core",
"butane_test_helper",
"butane_test_macros",
"example",
"examples/newtype",
"examples/getting_started",
"examples/getting_started_async",
]

[workspace.package]
Expand All @@ -18,23 +20,25 @@ repository = "https://github.com/Electron100/butane"
version = "0.7.0"

[workspace.dependencies]
async-trait = "0.1"
butane = { version = "0.7", path = "butane" }
butane_cli = { path = "butane_cli" }
butane_core = { version = "0.7", path = "butane_core" }
butane_codegen = { version = "0.7", path = "butane_codegen" }
butane_test_helper = { path = "butane_test_helper" }
butane_test_macros = { path = "butane_test_macros" }
cfg-if = "^1.0"
chrono = { version = "0.4.25", default-features = false, features = [
"serde",
"std",
] }
crossbeam-channel = "0.5"
env_logger = "0.11"
fake = "2.6"
log = "0.4"
nonempty = "0.10"
once_cell = "1.5.2"
paste = "1.0.11"
postgres = "0.19"
proc-macro2 = { version = "1.0", default-features = false }
quote = { version = "1.0", default-features = false }
r2d2 = "0.8"
Expand All @@ -45,8 +49,17 @@ serde_json = "1.0"
sqlparser = "0.44"
syn = { version = "2", features = ["extra-traits", "full"] }
tempfile = "3.10"
tokio = { version = "1"}
tokio-postgres = "0.7"
tokio-test = { version = "0.4"}
uuid = "1.2"

# Switch back to crates.io version once one is published containing
# the referenced commit. Anything newer than 0.2.4 should have it.
[workspace.dependencies.maybe-async-cfg]
git = "https://github.com/nvksv/maybe-async-cfg.git"
rev = "b35f2f42e9b12a25fc731376fe6cdcf41869b2da"

[workspace.metadata.release]
allow-branch = ["master"]
push = false
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ lint :

lint-ci : doclint lint spellcheck check-fmt

check : build test doclint lint spellcheck check-fmt
check : build doclint lint spellcheck check-fmt test


test :
Expand All @@ -31,12 +31,13 @@ fmt :

check-fmt :
$(CARGO_NIGHTLY) fmt --check
editorconfig-checker

spellcheck :
typos

doclint :
RUSTDOCFLAGS="-D warnings" $(CARGO_NIGHTLY) doc --no-deps --all-features
RUSTDOCFLAGS="-D warnings" RUSTFLAGS="-A elided_named_lifetimes" $(CARGO_NIGHTLY) doc --no-deps --all-features

doc :
cd butane && $(CARGO_NIGHTLY) doc --no-deps --all-features
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,34 @@ enabled: you will want to enable `sqlite` and/or `pg`:
the API will win.

## Migration of Breaking Changes
### 0.8 (not yet released)

This is a major release which adds Async support. Effort has been made
to keep the sync experience as unchanged as possible. Async versions
of many types have been added, but the sync ones generally retain
their previous names.

In order to allow sync and async code to look as
similar as possible for types and traits which do not otherwise need
separate sync and async variants, several "Ops" traits have been
introduced which contain methods split off from prior types and traits.

For example, if `obj` is an instance of
[`DataObject`](https://docs.rs/butane/latest/butane/trait.DataObject.html),
then you may call `obj.save(conn)` (sync) or `obj.save(conn).await`
(async). The `save` method no longer lives on `DataObject`. Instead,
you must use either `butane::DataObjectOpsSync` or
`butane::DataObjectOpsAsync`. Which trait is in scope will determine
whether the `save` method is sync or async.

The Ops traits are:
* `DataObjectOpsSync` / `DataObjectOpsAsync` (for use with [`DataObject`](https://docs.rs/butane/latest/butane/trait.DataObject.html))
* `QueryOpsSync` / `QueryOpsSync` (for use with [`Query`](https://docs.rs/butane/latest/butane/query/struct.Query.html),
less commonly needed directly if you use the [`query`](https://docs.rs/butane/latest/butane/macro.query.html) or
[`filter`](https://docs.rs/butane/latest/butane/macro.filter.html) macros)
* `ForeignKeyOpsSync` / `ForeignKeyOpsAsync` (for use with [`ForeignKey`](https://docs.rs/butane/latest/butane/struct.ForeignKey.html))
* `ManyOpsSync` / `ManyOpsAsync` (for use with [`Many`](https://docs.rs/butane/latest/butane/struct.Many.html))

### 0.7
#### `AutoPk`
Replace model fields like
Expand Down
13 changes: 13 additions & 0 deletions async_checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
* [x] Clean up pattern for sync/async variants. Inconsistent between suffix and module
* [x] Tests should run against sync and async
* [x] Ensure Postgres works in sync
* [x] Re-enable R2D2 for sync
* [x] Fix `#[async_trait(?Send)]` to set up Send bound again as it's required for e.g. `tokio::spawn`
* [x] Separate sync and async examples
* [x] Ensure sqlite works in async
* [x] Fully support sync too. Using async should not be required
* [ ] Clean up miscellaneous TODOs
* [ ] Establish soundness for unsafe sections of AsyncAdapter
* [ ] Consider publishing `AsyncAdapter` into its own crate
* [ ] Should async and/or async_adapter be under a separate feature?
* [ ] Integrate deadpool or bb8 for async connection pool
7 changes: 6 additions & 1 deletion butane/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ tls = ["butane_core/tls"]
uuid = ["butane_codegen/uuid", "butane_core/uuid"]

[dependencies]
async-trait = { workspace = true }
butane_codegen = { workspace = true }
butane_core = { workspace = true }

[dev-dependencies]
butane_test_helper = { workspace = true }
butane_test_macros = { workspace = true }
cfg-if = { workspace = true }
paste = { workspace = true }
chrono = { workspace = true }
Expand All @@ -41,9 +43,12 @@ geo-types = "0.7"
log.workspace = true
nonempty.workspace = true
quote = { workspace = true }
maybe-async-cfg.workspace = true
proc-macro2 = { workspace = true }
once_cell = { workspace = true }
postgres = { features = ["with-geo-types-0_7"], workspace = true }
tokio = { workspace = true, features = ["macros"] }
tokio-postgres = { features = ["with-geo-types-0_7"], workspace = true }
tokio-test = { workspace = true }
rand = { workspace = true }
r2d2_for_test = { package = "r2d2", version = "0.8" }
rusqlite = { workspace = true }
Expand Down
66 changes: 52 additions & 14 deletions butane/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
pub use butane_codegen::{butane_type, dataresult, model, FieldType, PrimaryKeyType};
pub use butane_core::custom;
pub use butane_core::fkey::ForeignKey;
pub use butane_core::internal;
pub use butane_core::many::Many;
pub use butane_core::many::{Many, ManyOpsAsync, ManyOpsSync};
pub use butane_core::migrations;
pub use butane_core::query;
pub use butane_core::{
AsPrimaryKey, AutoPk, DataObject, DataResult, Error, FieldType, FromSql, PrimaryKeyType,
Result, SqlType, SqlVal, SqlValRef, ToSql,
AsPrimaryKey, AutoPk, DataObject, DataObjectOpsAsync, DataObjectOpsSync, DataResult, Error,
FieldType, FromSql, PrimaryKeyType, Result, SqlType, SqlVal, SqlValRef, ToSql,
};

pub mod db {
Expand Down Expand Up @@ -160,23 +159,62 @@ macro_rules! colname {
#[macro_export]
macro_rules! find {
($dbobj:ident, $filter:expr, $conn:expr) => {
butane::query!($dbobj, $filter)
.limit(1)
.load($conn)
butane::query::QueryOpsSync::load(butane::query!($dbobj, $filter).limit(1), $conn)
.and_then(|mut results| results.pop().ok_or(butane::Error::NoSuchObject))
};
}

pub mod prelude {
//! Prelude module to improve ergonomics.
//!
//! Its use is recommended, but not required. If not used, the use
//! of butane's macros may require some of its re-exports to be
//! used manually.
pub use butane_core::db::BackendConnection;
/// Like [`find`], but for async.
#[macro_export]
macro_rules! find_async {
($dbobj:ident, $filter:expr, $conn:expr) => {
butane::query::QueryOpsAsync::load(butane::query!($dbobj, $filter).limit(1), $conn)
.await
.and_then(|mut results| results.pop().ok_or(butane::Error::NoSuchObject))
};
}

mod prelude_common {
#[doc(no_inline)]
pub use crate::DataObject;
#[doc(no_inline)]
pub use crate::DataResult;
}

pub mod prelude {
//! Prelude module to improve ergonomics. Brings certain traits into scope.
//! This module is for sync operation. For asynchronous, see [`super::prelude_async`].
//!
//! Its use is recommended, but not required.

pub use super::prelude_common::*;

pub use butane_core::db::BackendConnection;
pub use butane_core::fkey::ForeignKeyOpsSync;
pub use butane_core::many::ManyOpsSync;
pub use butane_core::query::QueryOpsSync;
pub use butane_core::DataObjectOpsSync;
}

pub mod prelude_async {
//! Prelude module to improve ergonomics in async operation. Brings certain traits into scope.
//!
//! Its use is recommended, but not required.
pub use super::prelude_common::*;

pub use butane_core::db::BackendConnectionAsync;
pub use butane_core::fkey::ForeignKeyOpsAsync;
pub use butane_core::many::ManyOpsAsync;
pub use butane_core::query::QueryOpsAsync;
pub use butane_core::DataObjectOpsAsync;
}

pub mod internal {
//! Internals used in macro-generated code.
//!
//! Do not use directly. Semver-exempt.

pub use async_trait::async_trait;

pub use butane_core::internal::*;
}
Loading
Loading