Skip to content

Commit 4f6a614

Browse files
committed
README organization and update
1 parent 3234f99 commit 4f6a614

File tree

1 file changed

+159
-156
lines changed

1 file changed

+159
-156
lines changed

README.adoc

+159-156
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,108 @@ Manual controlling is supported and explained later in this document.
99
All locks acquired by lock implementations in this project will expire after 10 seconds, timeout after 1 second if unable to acquire lock and sleep for 50 ms between retries.
1010
These options are customizable per annotation.
1111

12+
== Using locks
13+
14+
To lock your methods you need to first enable locking as described in the previous section.
15+
16+
Spring `https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html[BeanPostProcessor]` will handle all `@Locked` methods including
17+
their aliases. The `type` field describes which implementation of the lock to use.
18+
To prevent repeating yourself if you plan on using the same implementation (as most people usually will), I've added alias support.
19+
They wrap the `@Locked` annotation and define the type used.
20+
21+
Each lock needs to define a https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html[SpEL] expression used to acquire the lock.
22+
To learn more about Spring aliases visit https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[this] link.
23+
24+
=== Lock refresh
25+
26+
Locks can be refreshed automatically on a regular interval. This allows methods that occasionally need to run longer than their expiration.
27+
Refreshing the lock periodically prolongs the expiration of its key(s). This means that the lock cannot be acquired by another resource as long as the resource using the lock does not
28+
end successfully. In case the resource holding the lock fails unexpectedly without releasing the lock, the lock will expire according to the last expiration that was written (that the last refresh
29+
has set).
30+
31+
=== Manually controlled locks
32+
33+
Sometimes you might want lock to be acquired when calling a specific method and get released only when it expires (throttling).
34+
35+
To acquire a lock that doesn't get released automatically set `manuallyReleased` to `true` on `@Locked` annotation.
36+
37+
For more grained control (e.g., locking in the middle of the method and releasing later in the code), inject the lock in your service and acquire the lock manually.
38+
39+
==== Example
40+
41+
[source,java]
42+
----
43+
@Component
44+
public class Example {
45+
46+
@Qualifier("simpleRedisLock")
47+
private Lock lock;
48+
49+
// other fields...
50+
51+
private void manuallyLocked() {
52+
// code before locking...
53+
54+
final String token = lock.acquire(keys, storeId, expiration, retry, timeout);
55+
56+
// check if you acquired a token
57+
if (StringUtils.isEmpty(token)) {
58+
throw new IllegalStateException("Lock not acquired!");
59+
}
60+
61+
// code after locking...
62+
63+
lock.release(keys, token, storeId);
64+
65+
// code after releasing the lock...
66+
}
67+
}
68+
----
69+
70+
=== Unsuccessful locks
71+
72+
If method cannot be locked, `DistributedLockException` will be thrown.
73+
74+
Method might not acquire the lock if:
75+
76+
. keys from SpEL expression cannot be resolved
77+
. another method acquired the lock
78+
. Lock implementation threw an exception
79+
80+
== Examples
81+
82+
Locking a method with the name _aliased_ in the document called _lock_ in MongoDB:
83+
84+
[source,java]
85+
----
86+
@MongoLocked(expression = "'aliased'", storeId = "lock")
87+
public void runLockedWithMongo() {
88+
// locked code
89+
}
90+
----
91+
92+
Locking with multiple keys determined in runtime, use SpEL, for an example:
93+
94+
[source,java]
95+
----
96+
@RedisMultiLocked(expression = "T(com.example.MyUtils).getNamesWithId(#p0)")
97+
public void runLockedWithRedis(final int id) {
98+
// locked code
99+
}
100+
----
101+
102+
This means that the `runLockedWithRedis` method will execute only if all keys evaluated by expression were acquired.
103+
104+
Locking with a custom lock implementation based on value of integer field `count`:
105+
106+
[source,java]
107+
----
108+
@Locked(type = MyCustomLock.class, expression = "getCount", prefix = "using:")
109+
public void runLockedWithMyCustomLock() {
110+
// locked code
111+
}
112+
----
113+
12114
== Enabling locking
13115

14116
The project contains several configurations and annotations to help you enable locking and customize it.
@@ -120,75 +222,8 @@ public class LockConfiguration {
120222
}
121223
----
122224

123-
== Changelog
124-
125-
Started tracking the changes since 1.2.0 so no changelogs available for earlier versions.
126-
127-
==== 1.4.0
128-
129-
- CHANGE: Switched back to Java 1.8 from 11 since most projects don't yet use 11
130-
131-
==== 1.3.0
132-
133-
- CHANGE: Updated Java from 1.8 to 11
134-
- CHANGE: Refactored lots of coupled code
135-
- CHANGE: Extracted lots of reusable components such as retriable locks for easier manual control of locks
136-
- BUGFIX: `LockBeanPostProcessor` will now fire after existing advisors to support transactional advisors
137-
138-
==== 1.2.2
139-
140-
- CHANGE: Removed explicit `ParameterNameDiscoverer` from `SpelKeyGenerator` which now uses the one provided by the `CachedExpressionEvaluator`
141-
- CHANGE: Used `AopUtils` once and passed the evaluated method to `SpelKeyGenerator` so it doesn't have to evaluate the same thing as `LockMethodInterceptor`
142-
143-
==== 1.2.1
144-
145-
- FEATURE: Lock refreshing has been added.
146-
Check the 'Lock refresh' chapter for more details
147-
- BUGFIX: `@RedisMultiLocked` was using `#executionPath` as prefix instead of an expression
148-
- BUGFIX: `@RedisMultiLocked` was using `expiration` and `timeout` in milliseconds instead of seconds
149-
150-
==== 1.2.0
151-
- FEATURE: Added a JavaDoc description to `com.github.alturkovic.lock.Lock.release()` method
152-
- CHANGE: Rearranged the parameters of the `com.github.alturkovic.lock.Lock.release()` method to be more consistent
153-
- CHANGE: Rearranged the parameters of the `com.github.alturkovic.lock.jdbc.service.JdbcLockSingleKeyService` methods to be more consistent
154-
- CHANGE: `EvaluationConvertException` and `LockNotAvailableException` now extend the `DistributedLockException`
155-
156225
== Importing into your project
157226

158-
=== Compatibility
159-
160-
|===
161-
|Version |Spring Boot version
162-
163-
|1.3.0
164-
|2.2.7.RELEASE
165-
166-
|1.2.2
167-
|2.1.0.RELEASE
168-
169-
|1.2.1
170-
|2.1.0.RELEASE
171-
172-
|1.2.0
173-
|2.1.0.RELEASE
174-
175-
|1.1.10
176-
|2.0.4.RELEASE
177-
178-
|1.1.9
179-
|2.0.4.RELEASE
180-
181-
|1.1.8
182-
|2.0.4.RELEASE
183-
184-
|1.1.7
185-
|2.0.3.RELEASE
186-
187-
|1.1.6 and lower
188-
|1.5.6.RELEASE
189-
190-
|===
191-
192227
=== Maven
193228

194229
Add the JitPack repository into your `pom.xml`.
@@ -217,107 +252,42 @@ To add the Redis dependency for an example, add the following under your `<depen
217252
</dependencies>
218253
----
219254

220-
== Using locks
221-
222-
To lock your methods you need to first enable locking as described in the previous section.
223-
224-
Spring `https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html[BeanPostProcessor]` will handle all `@Locked` methods including
225-
their aliases. The `type` field describes which implementation of the lock to use.
226-
To prevent repeating yourself if you plan on using the same implementation (as most people usually will), I've added alias support.
227-
They wrap the `@Locked` annotation and define the type used.
228-
229-
Each lock needs to define a https://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html[SpEL] expression used to acquire the lock.
230-
To learn more about Spring aliases visit https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model[this] link.
231-
232-
=== Lock refresh
233-
234-
Locks can be refreshed automatically on a regular interval. This allows methods that occasionally need to run longer than their expiration.
235-
Refreshing the lock periodically prolongs the expiration of its key(s). This means that the lock cannot be acquired by another resource as long as the resource using the lock does not
236-
end successfully. In case the resource holding the lock fails unexpectedly without releasing the lock, the lock will expire according to the last expiration that was written (that the last refresh
237-
has set).
238-
239-
=== Manually controlled locks
240-
241-
Sometimes you might want lock to be acquired when calling a specific method and get released only when it expires (throttling).
242-
243-
To acquire a lock that doesn't get released automatically set `manuallyReleased` to `true` on `@Locked` annotation.
244-
245-
For more grained control (e.g., locking in the middle of the method and releasing later in the code), inject the lock in your service and acquire the lock manually.
246-
247-
==== Example
248-
249-
[source,java]
250-
----
251-
@Component
252-
public class Example {
253-
254-
@Qualifier("simpleRedisLock")
255-
private Lock lock;
256-
257-
// other fields...
258-
259-
private void manuallyLocked() {
260-
// code before locking...
261-
262-
final String token = lock.acquire(keys, storeId, expiration, retry, timeout);
263-
264-
// check if you acquired a token
265-
if (StringUtils.isEmpty(token)) {
266-
throw new IllegalStateException("Lock not acquired!");
267-
}
268-
269-
// code after locking...
270-
271-
lock.release(keys, token, storeId);
272-
273-
// code after releasing the lock...
274-
}
275-
}
276-
----
255+
=== Compatibility
277256

278-
=== Unsuccessful locks
257+
|===
258+
|Version |Spring Boot version
279259

280-
If method cannot be locked, `DistributedLockException` will be thrown.
260+
|1.4.0
261+
|2.2.7.RELEASE
281262

282-
Method might not acquire the lock if:
263+
|1.3.0
264+
|2.2.7.RELEASE
283265

284-
. keys from SpEL expression cannot be resolved
285-
. another method acquired the lock
286-
. Lock implementation threw an exception
266+
|1.2.2
267+
|2.1.0.RELEASE
287268

288-
== Examples
269+
|1.2.1
270+
|2.1.0.RELEASE
289271

290-
Locking a method with the name _aliased_ in the document called _lock_ in MongoDB:
272+
|1.2.0
273+
|2.1.0.RELEASE
291274

292-
[source,java]
293-
----
294-
@MongoLocked(expression = "'aliased'", storeId = "lock")
295-
public void runLockedWithMongo() {
296-
// locked code
297-
}
298-
----
275+
|1.1.10
276+
|2.0.4.RELEASE
299277

300-
Locking with multiple keys determined in runtime, use SpEL, for an example:
278+
|1.1.9
279+
|2.0.4.RELEASE
301280

302-
[source,java]
303-
----
304-
@RedisMultiLocked(expression = "T(com.example.MyUtils).getNamesWithId(#p0)")
305-
public void runLockedWithRedis(final int id) {
306-
// locked code
307-
}
308-
----
281+
|1.1.8
282+
|2.0.4.RELEASE
309283

310-
This means that the `runLockedWithRedis` method will execute only if all keys evaluated by expression were acquired.
284+
|1.1.7
285+
|2.0.3.RELEASE
311286

312-
Locking with a custom lock implementation based on value of integer field `count`:
287+
|1.1.6 and lower
288+
|1.5.6.RELEASE
313289

314-
[source,java]
315-
----
316-
@Locked(type = MyCustomLock.class, expression = "getCount", prefix = "using:")
317-
public void runLockedWithMyCustomLock() {
318-
// locked code
319-
}
320-
----
290+
|===
321291

322292
== SpEL key generator
323293

@@ -345,3 +315,36 @@ For more examples, take a look at `com.github.alturkovic.lock.key.SpelKeyGenerat
345315

346316
If you want to use custom lock implementations, simply implement `Lock` interface and register it in a configuration.
347317
You can also create an alias for your lock so you don't have to specify `@Locked` type field.
318+
319+
== Changelog
320+
321+
Started tracking the changes since 1.2.0 so no changelogs available for earlier versions.
322+
323+
==== 1.4.0
324+
325+
- CHANGE: Switched back to Java 1.8 from 11 since most projects don't yet use 11
326+
327+
==== 1.3.0
328+
329+
- CHANGE: Updated Java from 1.8 to 11
330+
- CHANGE: Refactored lots of coupled code
331+
- CHANGE: Extracted lots of reusable components such as retriable locks for easier manual control of locks
332+
- BUGFIX: `LockBeanPostProcessor` will now fire after existing advisors to support transactional advisors
333+
334+
==== 1.2.2
335+
336+
- CHANGE: Removed explicit `ParameterNameDiscoverer` from `SpelKeyGenerator` which now uses the one provided by the `CachedExpressionEvaluator`
337+
- CHANGE: Used `AopUtils` once and passed the evaluated method to `SpelKeyGenerator` so it doesn't have to evaluate the same thing as `LockMethodInterceptor`
338+
339+
==== 1.2.1
340+
341+
- FEATURE: Lock refreshing has been added.
342+
Check the 'Lock refresh' chapter for more details
343+
- BUGFIX: `@RedisMultiLocked` was using `#executionPath` as prefix instead of an expression
344+
- BUGFIX: `@RedisMultiLocked` was using `expiration` and `timeout` in milliseconds instead of seconds
345+
346+
==== 1.2.0
347+
- FEATURE: Added a JavaDoc description to `com.github.alturkovic.lock.Lock.release()` method
348+
- CHANGE: Rearranged the parameters of the `com.github.alturkovic.lock.Lock.release()` method to be more consistent
349+
- CHANGE: Rearranged the parameters of the `com.github.alturkovic.lock.jdbc.service.JdbcLockSingleKeyService` methods to be more consistent
350+
- CHANGE: `EvaluationConvertException` and `LockNotAvailableException` now extend the `DistributedLockException`

0 commit comments

Comments
 (0)