Skip to content

Commit 6422c12

Browse files
committed
Merge pull request #17 from maciej-rosiek/master
Refactored AdvisoryLock to more extendable form
2 parents 90600d7 + 87a698f commit 6422c12

File tree

17 files changed

+261
-34
lines changed

17 files changed

+261
-34
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ To use SProcWrapper, add the following lines to your pom.xml:
1717
<dependency>
1818
<groupId>de.zalando</groupId>
1919
<artifactId>zalando-sprocwrapper</artifactId>
20-
<version>1.2.4</version>
20+
<version>1.3.0</version>
2121
</dependency>
2222
```
2323

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
create type partial_object as (
2+
name text
3+
);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CREATE OR REPLACE FUNCTION get_partial_object(p partial_object)
2+
RETURNS partial_object AS
3+
$$
4+
DECLARE
5+
r partial_object;
6+
BEGIN
7+
r.name := p.name;
8+
return r;
9+
END;
10+
$$ LANGUAGE plpgsql SECURITY DEFINER;

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>de.zalando</groupId>
66
<artifactId>zalando-sprocwrapper</artifactId>
7-
<version>1.2.4</version>
7+
<version>1.3.0</version>
88
<packaging>jar</packaging>
99
<name>Stored Procedure Wrapper</name>
1010
<description>Library to make PostgreSQL stored procedures available through simple Java "*SProcService" interfaces including automatic object serialization and deserialization (using typemapper and convention-over-configuration). Supports sharding, advisory locking, statement timeouts and PostgreSQL types such as enums and hstore.</description>

src/main/java/de/zalando/sprocwrapper/SProcCall.java

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
import java.lang.annotation.RetentionPolicy;
77
import java.lang.annotation.Target;
88

9+
import java.util.Objects;
10+
11+
import com.google.common.base.Preconditions;
12+
913
/**
1014
* @author jmussler
1115
*/
@@ -14,24 +18,75 @@
1418
@Inherited
1519
public @interface SProcCall {
1620

17-
public static enum AdvisoryLock {
18-
NO_LOCK(0L),
19-
LOCK_ONE(1L);
21+
public static class AdvisoryLock {
2022

21-
/*
22-
* Add more values to this enum if you need additional types of locks
23-
*/
23+
public static class NoLock {
24+
public static final String NAME = "NO_LOCK";
25+
public static final long LOCK_ID = 0L;
26+
public static final AdvisoryLock LOCK = new AdvisoryLock(NAME, LOCK_ID);
27+
}
28+
29+
public static class LockOne {
30+
public static final String NAME = "LOCK_ONE";
31+
public static final long LOCK_ID = 1L;
32+
public static final AdvisoryLock LOCK = new AdvisoryLock(NAME, LOCK_ID);
33+
}
34+
35+
private final String name;
36+
private final long lockId;
37+
38+
public AdvisoryLock(final String name, final long lockId) {
39+
Preconditions.checkNotNull(name, "Name parameter cannot be null.");
40+
Preconditions.checkArgument(lockId == NoLock.LOCK_ID && Objects.equals(name, NoLock.NAME)
41+
|| lockId != NoLock.LOCK_ID && !Objects.equals(name, NoLock.NAME),
42+
"LockId parameter is different than %s (%s) but the name parameter was not changed: [name: %s, lockId: %s]",
43+
NoLock.LOCK_ID, NoLock.NAME, name, lockId);
44+
this.name = name;
45+
this.lockId = lockId;
46+
}
47+
48+
public String getName() {
49+
return name;
50+
}
2451

25-
private AdvisoryLock(final long sprocId) {
26-
this.sprocId = sprocId;
52+
public long getLockId() {
53+
return lockId;
2754
}
2855

29-
private final long sprocId;
56+
@Override
57+
public boolean equals(final Object o) {
58+
if (this == o) {
59+
return true;
60+
}
3061

31-
public long getSprocId() {
32-
return sprocId;
62+
if (o == null || getClass() != o.getClass()) {
63+
return false;
64+
}
65+
66+
final AdvisoryLock that = (AdvisoryLock) o;
67+
68+
if (lockId != that.lockId) {
69+
return false;
70+
}
71+
72+
if (!name.equals(that.name)) {
73+
return false;
74+
}
75+
76+
return true;
3377
}
3478

79+
@Override
80+
public int hashCode() {
81+
int result = name.hashCode();
82+
result = 31 * result + (int) (lockId ^ (lockId >>> 32));
83+
return result;
84+
}
85+
86+
@Override
87+
public String toString() {
88+
return "AdvisoryLock{" + "name='" + name + '\'' + ", lockId=" + lockId + '}';
89+
}
3590
}
3691

3792
public static enum Validate {
@@ -94,7 +149,10 @@ public static enum WriteTransaction {
94149

95150
long timeoutInMilliSeconds() default 0;
96151

97-
AdvisoryLock adivsoryLockType() default AdvisoryLock.NO_LOCK;
152+
long adivsoryLockId() default AdvisoryLock.NoLock.LOCK_ID;
153+
154+
String adivsoryLockName() default AdvisoryLock.NoLock.NAME;
98155

99156
Validate validate() default Validate.AS_DEFINED_IN_SERVICE;
157+
100158
}

src/main/java/de/zalando/sprocwrapper/proxy/SProcProxyBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,9 @@ public static <T> T build(final DataSourceProvider d, final Class<T> c) {
136136

137137
storedProcedure = new StoredProcedure(name, method.getGenericReturnType(), sprocStrategy,
138138
scA.runOnAllShards(), scA.searchShards(), scA.parallel(), resultMapper,
139-
scA.timeoutInMilliSeconds(), scA.adivsoryLockType(), useValidation, scA.readOnly(),
140-
writeTransaction);
139+
scA.timeoutInMilliSeconds(),
140+
new SProcCall.AdvisoryLock(scA.adivsoryLockName(), scA.adivsoryLockId()), useValidation,
141+
scA.readOnly(), writeTransaction);
141142
if (!"".equals(scA.sql())) {
142143
storedProcedure.setQuery(scA.sql());
143144
}

src/main/java/de/zalando/sprocwrapper/proxy/StoredProcedure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public StoredProcedure(final String name, final java.lang.reflect.Type genericTy
152152
}
153153
}
154154

155-
if (this.timeout > 0 || this.adivsoryLock != AdvisoryLock.NO_LOCK) {
155+
if (this.timeout > 0 || (this.adivsoryLock != null && !(this.adivsoryLock.equals(AdvisoryLock.NoLock.LOCK)))) {
156156

157157
// Wrapper provides locking and changing of session settings functionality
158158
this.executor = new ExecutorWrapper(executor, this.timeout, this.adivsoryLock);

src/main/java/de/zalando/sprocwrapper/proxy/executors/ExecutorWrapper.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ private void resetTimeout(final Connection conn) throws SQLException {
6060
}
6161

6262
private boolean lockAdvisoryLock(final Connection conn) throws SQLException {
63-
if (lock == AdvisoryLock.NO_LOCK) {
63+
if (lock == null || lock.equals(AdvisoryLock.NoLock.LOCK)) {
6464
return true;
6565
}
6666

6767
final Statement st = conn.createStatement();
68-
final ResultSet rs = st.executeQuery("SELECT pg_advisory_lock(" + lock.getSprocId() + ") AS \"" + lock.name()
69-
+ "\";");
68+
final ResultSet rs = st.executeQuery("SELECT pg_advisory_lock(" + lock.getLockId() + ") AS \"" + lock
69+
.getName() + "\";");
7070

7171
boolean b = false;
7272
if (rs.next()) {
@@ -79,12 +79,12 @@ private boolean lockAdvisoryLock(final Connection conn) throws SQLException {
7979
}
8080

8181
private boolean unlockAdvisoryLock(final Connection conn) throws SQLException {
82-
if (lock == AdvisoryLock.NO_LOCK) {
82+
if (lock == null || lock.equals(AdvisoryLock.NoLock.LOCK)) {
8383
return true;
8484
}
8585

8686
final Statement st = conn.createStatement();
87-
final ResultSet rs = st.executeQuery("SELECT pg_advisory_unlock(" + lock.getSprocId() + ")");
87+
final ResultSet rs = st.executeQuery("SELECT pg_advisory_unlock(" + lock.getLockId() + ")");
8888
boolean b = false;
8989
if (rs.next()) {
9090
b = rs.getBoolean(1);
@@ -108,7 +108,7 @@ public Object executeSProc(final DataSource ds, final String sql, final Object[]
108108
setTimeout(sameConnDs.getConnection());
109109

110110
if (!lockAdvisoryLock(sameConnDs.getConnection())) {
111-
throw new RuntimeException("Could not acquire AdvisoryLock " + lock.name());
111+
throw new RuntimeException("Could not acquire AdvisoryLock " + lock.getName());
112112
}
113113

114114
return executor.executeSProc(sameConnDs, sql, args, types, invocationContext, returnType);
@@ -130,7 +130,7 @@ public Object executeSProc(final DataSource ds, final String sql, final Object[]
130130
}
131131

132132
// unlock in all cases, locks not owned by this session cannot be unlocked
133-
if (lock != AdvisoryLock.NO_LOCK) {
133+
if (lock != null && !lock.equals(AdvisoryLock.NoLock.LOCK)) {
134134
try {
135135
unlockAdvisoryLock(sameConnDs.getConnection());
136136
} catch (final SQLException ex) {

src/main/java/de/zalando/typemapper/annotations/DatabaseType.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@
2020
* Flattens hierarchical structure of object and makes parent fields exposed to PgTypeHelper.
2121
*/
2222
boolean inheritance() default false;
23+
24+
/**
25+
* Annotated java class can have more @DatabaseField annotated fields than corresponding database type.
26+
*/
27+
boolean partial() default false;
28+
2329
}

src/main/java/de/zalando/typemapper/core/DatabaseFieldDescriptor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ public int getPosition() {
4040
public Class<? extends ObjectMapper<?>> getMapper() {
4141
return mapper;
4242
}
43+
4344
}

0 commit comments

Comments
 (0)