Skip to content

Commit 3a86263

Browse files
committed
tests: Fix issues with hook tests
1 parent 10fd639 commit 3a86263

4 files changed

Lines changed: 35 additions & 26 deletions

File tree

ENHANCEMENTS.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,16 @@ config :my_app, MyApp.Repo,
355355
**Reason**: Rustler threading model incompatibility
356356

357357
**Why Not Supported**:
358-
Both update hooks and authorizer hooks are fundamentally incompatible with Rustler's threading model:
358+
Both update hooks and authoriser hooks are fundamentally incompatible with Rustler's threading model:
359359

360360
1. **Update Hooks Problem**:
361361
- SQLite's update hook callback runs synchronously during INSERT/UPDATE/DELETE operations
362362
- Callback executes on Erlang scheduler threads (managed by BEAM)
363363
- Rustler's `OwnedEnv::send_and_clear()` can ONLY be called from unmanaged threads
364364
- Calling `send_and_clear()` from managed thread causes panic: "current thread is managed"
365365

366-
2. **Authorizer Hooks Problem**:
367-
- SQLite's authorizer callback is synchronous and expects immediate response (Allow/Deny/Ignore)
366+
2. **Authoriser Hooks Problem**:
367+
- SQLite's authoriser callback is synchronous and expects immediate response (Allow/Deny/Ignore)
368368
- Would require blocking Rust thread waiting for Elixir response
369369
- No safe way to do synchronous Rust→Elixir→Rust calls
370370
- Blocking on scheduler threads can cause deadlocks
@@ -377,8 +377,8 @@ For **Change Data Capture / Real-time Updates**:
377377
- Polling-based CDC with timestamps
378378
- Phoenix.Tracker for state tracking
379379

380-
For **Row-Level Security / Authorization**:
381-
- Application-level authorization checks before queries
380+
For **Row-Level Security / Authorisation**:
381+
- Application-level authorisation checks before queries
382382
- Database views with WHERE clauses
383383
- Query rewriting in Ecto
384384
- Connection-level privileges
@@ -445,13 +445,13 @@ For **Row-Level Security / Authorization**:
445445
### Potential Enhancements
446446
1. **Haversine Formula**: Implement actual geographic distance calculations for accuracy
447447
2. **Higher Dimensions**: Support for more complex geospatial data (elevation, time, etc.)
448-
3. **Index Optimization**: Add spatial indexes for performance on large datasets
448+
3. **Index Optimisation**: Add spatial indexes for performance on large datasets
449449
4. **Batch Queries**: Use batch operations for multiple location lookups
450450
5. **Clustering**: Find geographic clusters of locations using vector analysis
451451

452452
### Real-World Applications
453453
- **Location-based services**: Find nearby restaurants, hotels, gas stations
454-
- **Delivery optimization**: Locate nearest warehouse to customer location
454+
- **Delivery optimisation**: Locate nearest warehouse to customer location
455455
- **Regional analytics**: Find closest office/branch in each region
456456
- **Social discovery**: Find nearby users, events, or meetup groups
457457
- **Asset tracking**: Locate nearest available equipment or resources
@@ -885,4 +885,4 @@ disallowed-methods = [
885885
8. **Ecto Integration Improvements**
886886
9. **P3 Low Priority Features**
887887

888-
This prioritization ensures we address the most critical production issues first, then focus on performance and reliability, before moving to nice-to-have features and advanced functionality.
888+
This prioritisation ensures we address the most critical production issues first, then focus on performance and reliability, before moving to nice-to-have features and advanced functionality.

lib/ecto_libsql/native.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -992,8 +992,8 @@ defmodule EctoLibSql.Native do
992992
- `:unsupported` - Always returns unsupported
993993
994994
"""
995-
def add_update_hook(%EctoLibSql.State{} = state, _pid \\ self()) do
996-
set_update_hook(state.conn_id, self())
995+
def add_update_hook(%EctoLibSql.State{} = state, pid \\ self()) do
996+
set_update_hook(state.conn_id, pid)
997997
end
998998

999999
@doc """

native/ecto_libsql/src/hooks.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
///
66
/// **CURRENT STATUS**: Both update hooks and authorizer hooks are currently **NOT SUPPORTED**
77
/// due to fundamental threading limitations with Rustler and the BEAM VM.
8-
use rustler::{Atom, LocalPid, NifResult};
8+
use rustler::{Atom, Env, LocalPid, NifResult};
99

1010
/// Set update hook for a connection
1111
///
@@ -62,8 +62,11 @@ use rustler::{Atom, LocalPid, NifResult};
6262
/// # Returns
6363
/// - `{:error, :unsupported}` - Always returns unsupported
6464
#[rustler::nif]
65-
pub fn set_update_hook(_conn_id: &str, _pid: LocalPid) -> NifResult<Atom> {
66-
Err(rustler::Error::Atom("unsupported"))
65+
pub fn set_update_hook(env: Env, _conn_id: &str, _pid: LocalPid) -> NifResult<(Atom, Atom)> {
66+
Ok((
67+
Atom::from_str(env, "error")?,
68+
Atom::from_str(env, "unsupported")?,
69+
))
6770
}
6871

6972
/// Clear update hook for a connection
@@ -76,8 +79,11 @@ pub fn set_update_hook(_conn_id: &str, _pid: LocalPid) -> NifResult<Atom> {
7679
/// # Returns
7780
/// - `{:error, :unsupported}` - Always returns unsupported
7881
#[rustler::nif]
79-
pub fn clear_update_hook(_conn_id: &str) -> NifResult<Atom> {
80-
Err(rustler::Error::Atom("unsupported"))
82+
pub fn clear_update_hook(env: Env, _conn_id: &str) -> NifResult<(Atom, Atom)> {
83+
Ok((
84+
Atom::from_str(env, "error")?,
85+
Atom::from_str(env, "unsupported")?,
86+
))
8187
}
8288

8389
/// Set authorizer hook for a connection
@@ -148,6 +154,9 @@ pub fn clear_update_hook(_conn_id: &str) -> NifResult<Atom> {
148154
/// # Returns
149155
/// - `{:error, :unsupported}` - Always returns unsupported
150156
#[rustler::nif]
151-
pub fn set_authorizer(_conn_id: &str, _pid: LocalPid) -> NifResult<Atom> {
152-
Err(rustler::Error::Atom("unsupported"))
157+
pub fn set_authorizer(env: Env, _conn_id: &str, _pid: LocalPid) -> NifResult<(Atom, Atom)> {
158+
Ok((
159+
Atom::from_str(env, "error")?,
160+
Atom::from_str(env, "unsupported")?,
161+
))
153162
}

test/hooks_test.exs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ defmodule EctoLibSql.HooksTest do
1313

1414
describe "add_update_hook/2 - NOT SUPPORTED" do
1515
test "returns :unsupported error", %{state: state} do
16-
assert :unsupported = Native.add_update_hook(state)
16+
assert {:error, :unsupported} = Native.add_update_hook(state)
1717
end
1818

1919
test "returns :unsupported with custom PID", %{state: state} do
2020
test_pid = self()
21-
assert :unsupported = Native.add_update_hook(state, test_pid)
21+
assert {:error, :unsupported} = Native.add_update_hook(state, test_pid)
2222
end
2323

2424
test "does not affect database operations", %{state: state} do
25-
:unsupported = Native.add_update_hook(state)
25+
{:error, :unsupported} = Native.add_update_hook(state)
2626

2727
# Database operations should still work
2828
{:ok, _, _, _state} =
@@ -47,27 +47,27 @@ defmodule EctoLibSql.HooksTest do
4747

4848
describe "remove_update_hook/1 - NOT SUPPORTED" do
4949
test "returns :unsupported error", %{state: state} do
50-
assert :unsupported = Native.remove_update_hook(state)
50+
assert {:error, :unsupported} = Native.remove_update_hook(state)
5151
end
5252

5353
test "can be called multiple times safely", %{state: state} do
54-
assert :unsupported = Native.remove_update_hook(state)
55-
assert :unsupported = Native.remove_update_hook(state)
54+
assert {:error, :unsupported} = Native.remove_update_hook(state)
55+
assert {:error, :unsupported} = Native.remove_update_hook(state)
5656
end
5757
end
5858

5959
describe "add_authorizer/2 - NOT SUPPORTED" do
6060
test "returns :unsupported error", %{state: state} do
61-
assert :unsupported = Native.add_authorizer(state)
61+
assert {:error, :unsupported} = Native.add_authorizer(state)
6262
end
6363

6464
test "returns :unsupported with custom PID", %{state: state} do
6565
test_pid = self()
66-
assert :unsupported = Native.add_authorizer(state, test_pid)
66+
assert {:error, :unsupported} = Native.add_authorizer(state, test_pid)
6767
end
6868

6969
test "does not affect database operations", %{state: state} do
70-
:unsupported = Native.add_authorizer(state)
70+
{:error, :unsupported} = Native.add_authorizer(state)
7171

7272
# Database operations should still work
7373
{:ok, _, _, _state} =

0 commit comments

Comments
 (0)