1515 */
1616package io .flamingock .community .sql .internal ;
1717
18+ import io .flamingock .internal .common .sql .SqlDialect ;
1819import io .flamingock .internal .core .store .lock .community .CommunityLockService ;
1920import io .flamingock .internal .core .store .lock .community .CommunityLockEntry ;
2021import io .flamingock .internal .core .store .lock .LockAcquisition ;
@@ -59,15 +60,28 @@ public void initialize(boolean autoCreate) {
5960 public LockAcquisition upsert (LockKey key , RunnerId owner , long leaseMillis ) {
6061 String keyStr = key .toString ();
6162 LocalDateTime expiresAt = LocalDateTime .now ().plusNanos (leaseMillis * 1_000_000 );
63+
6264 try (Connection conn = dataSource .getConnection ()) {
63- CommunityLockEntry existing = getLockEntry (conn , keyStr );
64- if (existing == null ||
65- owner .toString ().equals (existing .getOwner ()) ||
66- LocalDateTime .now ().isAfter (existing .getExpiresAt ())) {
67- upsertLockEntry (conn , keyStr , owner .toString (), expiresAt );
68- } else {
69- throw new LockServiceException ("upsert" , keyStr ,
70- "Still locked by " + existing .getOwner () + " until " + existing .getExpiresAt ());
65+ conn .setAutoCommit (false );
66+ try {
67+ CommunityLockEntry existing = getLockEntry (conn , keyStr );
68+ if (existing == null ||
69+ owner .toString ().equals (existing .getOwner ()) ||
70+ LocalDateTime .now ().isAfter (existing .getExpiresAt ())) {
71+ upsertLockEntry (conn , keyStr , owner .toString (), expiresAt );
72+ if (dialectHelper .getSqlDialect () != SqlDialect .SQLSERVER && dialectHelper .getSqlDialect () != SqlDialect .SYBASE ) {
73+ conn .commit ();
74+ }
75+ } else {
76+ conn .rollback ();
77+ throw new LockServiceException ("upsert" , keyStr ,
78+ "Still locked by " + existing .getOwner () + " until " + existing .getExpiresAt ());
79+ }
80+ } catch (Exception e ) {
81+ conn .rollback ();
82+ throw e ;
83+ } finally {
84+ conn .setAutoCommit (true );
7185 }
7286 } catch (SQLException e ) {
7387 throw new LockServiceException ("upsert" , keyStr , e .getMessage ());
@@ -79,13 +93,26 @@ public LockAcquisition upsert(LockKey key, RunnerId owner, long leaseMillis) {
7993 public LockAcquisition extendLock (LockKey key , RunnerId owner , long leaseMillis ) throws LockServiceException {
8094 String keyStr = key .toString ();
8195 LocalDateTime expiresAt = LocalDateTime .now ().plusNanos (leaseMillis * 1_000_000 );
96+
8297 try (Connection conn = dataSource .getConnection ()) {
83- CommunityLockEntry existing = getLockEntry (conn , keyStr );
84- if (existing != null && owner .toString ().equals (existing .getOwner ())) {
85- upsertLockEntry (conn , keyStr , owner .toString (), expiresAt );
86- } else {
87- throw new LockServiceException ("extendLock" , keyStr ,
88- "Lock belongs to " + (existing != null ? existing .getOwner () : "none" ));
98+ conn .setAutoCommit (false );
99+ try {
100+ CommunityLockEntry existing = getLockEntry (conn , keyStr );
101+ if (existing != null && owner .toString ().equals (existing .getOwner ())) {
102+ upsertLockEntry (conn , keyStr , owner .toString (), expiresAt );
103+ if (dialectHelper .getSqlDialect () != SqlDialect .SQLSERVER && dialectHelper .getSqlDialect () != SqlDialect .SYBASE ) {
104+ conn .commit ();
105+ }
106+ } else {
107+ conn .rollback ();
108+ throw new LockServiceException ("extendLock" , keyStr ,
109+ "Lock belongs to " + (existing != null ? existing .getOwner () : "none" ));
110+ }
111+ } catch (Exception e ) {
112+ conn .rollback ();
113+ throw e ;
114+ } finally {
115+ conn .setAutoCommit (true );
89116 }
90117 } catch (SQLException e ) {
91118 throw new LockServiceException ("extendLock" , keyStr , e .getMessage ());
@@ -139,7 +166,7 @@ private CommunityLockEntry getLockEntry(Connection conn, String key) throws SQLE
139166 try (ResultSet rs = ps .executeQuery ()) {
140167 if (rs .next ()) {
141168 return new CommunityLockEntry (
142- rs .getString ("key" ),
169+ rs .getString (1 ), // key column
143170 LockStatus .valueOf (rs .getString ("status" )),
144171 rs .getString ("owner" ),
145172 rs .getTimestamp ("expires_at" ).toLocalDateTime ()
@@ -151,13 +178,30 @@ private CommunityLockEntry getLockEntry(Connection conn, String key) throws SQLE
151178 }
152179
153180 private void upsertLockEntry (Connection conn , String key , String owner , LocalDateTime expiresAt ) throws SQLException {
154- try (PreparedStatement ps = conn .prepareStatement (
155- dialectHelper .getInsertOrUpdateLockSqlString (lockRepositoryName ))) {
156- ps .setString (1 , key );
157- ps .setString (2 , LockStatus .LOCK_HELD .name ());
158- ps .setString (3 , owner );
159- ps .setTimestamp (4 , Timestamp .valueOf (expiresAt ));
160- ps .executeUpdate ();
181+ String sql = dialectHelper .getInsertOrUpdateLockSqlString (lockRepositoryName );
182+
183+ if (dialectHelper .getSqlDialect () == SqlDialect .SQLSERVER || dialectHelper .getSqlDialect () == SqlDialect .SYBASE ) {
184+ // For SQL Server, the SQL already contains transaction management
185+ try (Statement stmt = conn .createStatement ()) {
186+ String formattedSql = sql .replace ("?" , "'" + LockStatus .LOCK_HELD .name () + "'" )
187+ .replaceFirst ("'[^']*'" , "'" + LockStatus .LOCK_HELD .name () + "'" )
188+ .replaceFirst ("'[^']*'" , "'" + owner + "'" )
189+ .replaceFirst ("'[^']*'" , "'" + Timestamp .valueOf (expiresAt ) + "'" )
190+ .replaceFirst ("'[^']*'" , "'" + key + "'" )
191+ .replaceFirst ("'[^']*'" , "'" + key + "'" )
192+ .replaceFirst ("'[^']*'" , "'" + LockStatus .LOCK_HELD .name () + "'" )
193+ .replaceFirst ("'[^']*'" , "'" + owner + "'" )
194+ .replaceFirst ("'[^']*'" , "'" + Timestamp .valueOf (expiresAt ) + "'" );
195+ stmt .execute (formattedSql );
196+ }
197+ } else {
198+ try (PreparedStatement ps = conn .prepareStatement (sql )) {
199+ ps .setString (1 , key );
200+ ps .setString (2 , LockStatus .LOCK_HELD .name ());
201+ ps .setString (3 , owner );
202+ ps .setTimestamp (4 , Timestamp .valueOf (expiresAt ));
203+ ps .executeUpdate ();
204+ }
161205 }
162206 }
163207}
0 commit comments