Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ ash_sqlite-*.tar
test_migration_path
test_snapshots_path

test/test.db
test/test.db-shm
test/test.db-wal
test/*test.db
test/*test.db-shm
test/*test.db-wal
9 changes: 8 additions & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,15 @@ if Mix.env() == :test do
pool: Ecto.Adapters.SQL.Sandbox,
migration_primary_key: [name: :id, type: :binary_id]

config :ash_sqlite, AshSqlite.TransactingRepo,
database: Path.join(__DIR__, "../test/transacting_test.db"),
pool_size: 1,
migration_lock: false,
pool: Ecto.Adapters.SQL.Sandbox,
migration_primary_key: [name: :id, type: :binary_id]

config :ash_sqlite,
ecto_repos: [AshSqlite.TestRepo],
ecto_repos: [AshSqlite.TestRepo, AshSqlite.TransactingRepo],
ash_domains: [
AshSqlite.Test.Domain
]
Expand Down
9 changes: 8 additions & 1 deletion lib/data_layer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,14 @@ defmodule AshSqlite.DataLayer do
def can?(_, :bulk_create), do: true
def can?(_, {:lock, _}), do: false

def can?(_, :transact), do: false
# def can?(_, :transact), do: false

def can?(resource, :transact) do
repo = AshSqlite.DataLayer.Info.repo(resource)

repo.config()[:transactions_enabled?]
end

def can?(_, :composite_primary_key), do: true
def can?(_, {:atomic, :update}), do: true
def can?(_, {:atomic, :upsert}), do: true
Expand Down
2 changes: 2 additions & 0 deletions lib/repo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule AshSqlite.Repo do

- `:tenant_migrations_path` - The path where your tenant migrations are stored (only relevant for a multitenant implementation)
- `:snapshots_path` - The path where the resource snapshots for the migration generator are stored.
- `:transactions_enabled?` - Due to [SQLite's single writer paradigm](https://sqlite.org/lang_transaction.html#read_transactions_versus_write_transactions) they are disabled by default. See the [transactions guide](/documentation/topics/transactions.md) for more information.
"""

@doc "Use this to inform the data layer about what extensions are installed"
Expand Down Expand Up @@ -56,6 +57,7 @@ defmodule AshSqlite.Repo do
|> Keyword.put(:installed_extensions, installed_extensions())
|> Keyword.put(:migrations_path, migrations_path())
|> Keyword.put(:case_sensitive_like, :on)
|> Keyword.put_new(:transactions_enabled?, false)

{:ok, new_config}
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"attributes": [
{
"default": "nil",
"size": null,
"type": "uuid",
"source": "id",
"references": null,
"allow_nil?": false,
"generated?": false,
"primary_key?": true
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "title",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "subtitle",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
}
],
"table": "transacting_posts",
"hash": "56FE4F305257AC15BFA6AFA639A1D0A069C932004E89966DE7136AD9C96E1F93",
"repo": "Elixir.AshSqlite.TransactingRepo",
"identities": [],
"custom_indexes": [],
"base_filter": null,
"custom_statements": [],
"multitenancy": {
"global": null,
"attribute": null,
"strategy": null
},
"has_create_action": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule AshSqlite.TransactingRepo.Migrations.AddTransactingRepo do
@moduledoc """
Updates resources based on their most recent snapshots.

This file was autogenerated with `mix ash_sqlite.generate_migrations`
"""

use Ecto.Migration

def up do
create table(:transacting_posts, primary_key: false) do
add :subtitle, :text
add :title, :text
add :id, :uuid, null: false, primary_key: true
end
end

def down do
drop table(:transacting_posts)
end
end
2 changes: 2 additions & 0 deletions test/support/domain.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule AshSqlite.Test.Domain do
@moduledoc false

use Ash.Domain

resources do
Expand All @@ -15,6 +16,7 @@ defmodule AshSqlite.Test.Domain do
resource(AshSqlite.Test.Account)
resource(AshSqlite.Test.Organization)
resource(AshSqlite.Test.Manager)
resource(AshSqlite.Test.TransactingPost)
end

authorization do
Expand Down
5 changes: 3 additions & 2 deletions test/support/repo_case.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ defmodule AshSqlite.RepoCase do
end

setup tags do
:ok = Sandbox.checkout(AshSqlite.TestRepo)
repo = tags[:repo] || AshSqlite.TestRepo
:ok = Sandbox.checkout(repo)

unless tags[:async] do
Sandbox.mode(AshSqlite.TestRepo, {:shared, self()})
Sandbox.mode(repo, {:shared, self()})
end

:ok
Expand Down
21 changes: 21 additions & 0 deletions test/support/transacting_post.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
defmodule AshSqlite.Test.TransactingPost do
@moduledoc false
use Ash.Resource,
domain: AshSqlite.Test.Domain,
data_layer: AshSqlite.DataLayer

sqlite do
table("transacting_posts")
repo AshSqlite.TransactingRepo
end

actions do
defaults([:read, :destroy, update: :*, create: :*])
end

attributes do
uuid_primary_key(:id, writable?: true)
attribute(:title, :string, public?: true)
attribute(:subtitle, :string, public?: true)
end
end
4 changes: 4 additions & 0 deletions test/support/transacting_repo.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule AshSqlite.TransactingRepo do
@moduledoc false
use AshSqlite.Repo, otp_app: :ash_sqlite, transactions_enabled?: true
end
4 changes: 3 additions & 1 deletion test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ ExUnit.start()
ExUnit.configure(stacktrace_depth: 100)

AshSqlite.TestRepo.start_link()

Ecto.Adapters.SQL.Sandbox.mode(AshSqlite.TestRepo, :manual)

AshSqlite.TransactingRepo.start_link()
Ecto.Adapters.SQL.Sandbox.mode(AshSqlite.TransactingRepo, :manual)
50 changes: 50 additions & 0 deletions test/transaction_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
defmodule AshSqlite.TransactionTest do
@moduledoc false
use AshSqlite.RepoCase, async: false

describe "transactions are allowed when enabled" do
@describetag repo: AshSqlite.TransactingRepo

alias AshSqlite.Test.TransactingPost, as: Post

test "manual transaction" do
post_id = Ash.UUID.generate()

Ash.transaction(Post, fn ->
Post
|> Ash.create!(
%{
id: post_id,
title: "George McFly Murdered",
subtitle: "Local Author Shot Dead"
},
transaction?: true
)
end)

Ash.get!(Post, post_id)
end
end

describe "transactions are disallowed when disabled" do
@describetag repo: AshSqlite.TestRepo
alias AshSqlite.Test.Post

test "manual transaction" do
post_id = Ash.UUID.generate()

Ash.transaction(Post, fn ->
Post
|> Ash.create!(
%{
id: post_id,
title: "George McFly Murdered"
},
transaction?: true
)
end)

Ash.get!(Post, post_id)
end
end
end