1+ use anyhow:: Context ;
2+ use async_trait:: async_trait;
3+ use spin_factor_sqlite:: Connection ;
4+ use spin_world:: v2:: sqlite as v2;
15use spin_world:: v2:: sqlite:: { self , RowResult } ;
2- use tracing:: { instrument, Level } ;
6+ use tokio:: sync:: OnceCell ;
7+
8+ /// A lazy wrapper around a [`LibSqlConnection`] that implements the [`Connection`] trait.
9+ pub struct LazyLibSqlConnection {
10+ url : String ,
11+ token : String ,
12+ // Since the libSQL client can only be created asynchronously, we wait until
13+ // we're in the `Connection` implementation to create. Since we only want to do
14+ // this once, we use a `OnceCell` to store it.
15+ inner : OnceCell < LibSqlConnection > ,
16+ }
17+
18+ impl LazyLibSqlConnection {
19+ pub fn new ( url : String , token : String ) -> Self {
20+ Self {
21+ url,
22+ token,
23+ inner : OnceCell :: new ( ) ,
24+ }
25+ }
26+
27+ pub async fn get_or_create_connection ( & self ) -> Result < & LibSqlConnection , v2:: Error > {
28+ self . inner
29+ . get_or_try_init ( || async {
30+ LibSqlConnection :: create ( self . url . clone ( ) , self . token . clone ( ) )
31+ . await
32+ . context ( "failed to create SQLite client" )
33+ } )
34+ . await
35+ . map_err ( |_| v2:: Error :: InvalidConnection )
36+ }
37+ }
38+
39+ #[ async_trait]
40+ impl Connection for LazyLibSqlConnection {
41+ async fn query (
42+ & self ,
43+ query : & str ,
44+ parameters : Vec < v2:: Value > ,
45+ ) -> Result < v2:: QueryResult , v2:: Error > {
46+ let client = self . get_or_create_connection ( ) . await ?;
47+ client. query ( query, parameters) . await
48+ }
49+
50+ async fn execute_batch ( & self , statements : & str ) -> anyhow:: Result < ( ) > {
51+ let client = self . get_or_create_connection ( ) . await ?;
52+ client. execute_batch ( statements) . await
53+ }
54+
55+ fn summary ( & self ) -> Option < String > {
56+ Some ( format ! ( "libSQL at {}" , self . url) )
57+ }
58+ }
359
60+ /// An open connection to a libSQL server.
461#[ derive( Clone ) ]
5- pub struct LibsqlClient {
62+ pub struct LibSqlConnection {
663 inner : libsql:: Connection ,
764}
865
9- impl LibsqlClient {
10- #[ instrument( name = "spin_sqlite_libsql.create_connection" , skip( token) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" ) ) ]
66+ impl LibSqlConnection {
1167 pub async fn create ( url : String , token : String ) -> anyhow:: Result < Self > {
1268 let db = libsql:: Builder :: new_remote ( url, token) . build ( ) . await ?;
1369 let inner = db. connect ( ) ?;
1470 Ok ( Self { inner } )
1571 }
1672}
1773
18- impl LibsqlClient {
19- #[ instrument( name = "spin_sqlite_libsql.query" , skip( self ) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , otel. name = query) ) ]
74+ impl LibSqlConnection {
2075 pub async fn query (
2176 & self ,
2277 query : & str ,
@@ -36,7 +91,6 @@ impl LibsqlClient {
3691 } )
3792 }
3893
39- #[ instrument( name = "spin_sqlite_libsql.execute_batch" , skip( self ) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "sqlite" , db. statements = statements) ) ]
4094 pub async fn execute_batch ( & self , statements : & str ) -> anyhow:: Result < ( ) > {
4195 self . inner . execute_batch ( statements) . await ?;
4296
0 commit comments