@@ -16,6 +16,7 @@ pub type Result<T> = std::result::Result<T, Error>;
1616
1717/// Default filename for the payjoin database
1818pub const DB_FILENAME : & str = "payjoin.sqlite" ;
19+ const SESSION_RETENTION_SECS : i64 = 30 * 24 * 60 * 60 ;
1920
2021/// Returns the current Unix timestamp in seconds
2122#[ inline]
@@ -109,6 +110,90 @@ impl Database {
109110 Ok ( was_seen_before)
110111 }
111112
113+ /// Removes old completed sessions and stale incomplete sessions plus their event logs.
114+ pub fn prune_expired_sessions ( & self ) -> Result < ( ) > {
115+ let cutoff = now ( ) - SESSION_RETENTION_SECS ;
116+ let mut conn = self . conn ( ) ;
117+ let tx = conn. transaction ( ) ?;
118+ let stale_send_session_ids = {
119+ let mut stmt = tx. prepare (
120+ "SELECT session_id FROM send_sessions
121+ WHERE (completed_at IS NOT NULL AND completed_at < ?1)
122+ OR (
123+ completed_at IS NULL
124+ AND session_id IN (
125+ SELECT session_id FROM send_session_events
126+ GROUP BY session_id
127+ HAVING MAX(created_at) < ?1
128+ )
129+ )
130+ OR (
131+ completed_at IS NULL
132+ AND session_id NOT IN (
133+ SELECT session_id FROM send_session_events
134+ )
135+ )" ,
136+ ) ?;
137+ let rows = stmt. query_map ( params ! [ cutoff] , |row| row. get :: < _ , i64 > ( 0 ) ) ?;
138+ let mut ids = Vec :: new ( ) ;
139+ for row in rows {
140+ ids. push ( row?) ;
141+ }
142+ ids
143+ } ;
144+ let stale_receive_session_ids = {
145+ let mut stmt = tx. prepare (
146+ "SELECT session_id FROM receive_sessions
147+ WHERE (completed_at IS NOT NULL AND completed_at < ?1)
148+ OR (
149+ completed_at IS NULL
150+ AND session_id IN (
151+ SELECT session_id FROM receive_session_events
152+ GROUP BY session_id
153+ HAVING MAX(created_at) < ?1
154+ )
155+ )
156+ OR (
157+ completed_at IS NULL
158+ AND session_id NOT IN (
159+ SELECT session_id FROM receive_session_events
160+ )
161+ )" ,
162+ ) ?;
163+ let rows = stmt. query_map ( params ! [ cutoff] , |row| row. get :: < _ , i64 > ( 0 ) ) ?;
164+ let mut ids = Vec :: new ( ) ;
165+ for row in rows {
166+ ids. push ( row?) ;
167+ }
168+ ids
169+ } ;
170+
171+ for session_id in stale_send_session_ids {
172+ tx. execute (
173+ "DELETE FROM send_session_events WHERE session_id = ?1" ,
174+ params ! [ session_id] ,
175+ ) ?;
176+ tx. execute (
177+ "DELETE FROM send_sessions WHERE session_id = ?1" ,
178+ params ! [ session_id] ,
179+ ) ?;
180+ }
181+
182+ for session_id in stale_receive_session_ids {
183+ tx. execute (
184+ "DELETE FROM receive_session_events WHERE session_id = ?1" ,
185+ params ! [ session_id] ,
186+ ) ?;
187+ tx. execute (
188+ "DELETE FROM receive_sessions WHERE session_id = ?1" ,
189+ params ! [ session_id] ,
190+ ) ?;
191+ }
192+
193+ tx. commit ( ) ?;
194+ Ok ( ( ) )
195+ }
196+
112197 /// Returns IDs of all active (incomplete) receive sessions
113198 pub fn get_recv_session_ids ( & self ) -> Result < Vec < SessionId > > {
114199 let conn = self . conn ( ) ;
0 commit comments