Skip to content

Commit 1490d53

Browse files
committed
documentation
1 parent dff36e3 commit 1490d53

1 file changed

Lines changed: 78 additions & 24 deletions

File tree

  • lib/src/main/kotlin/org/veupathdb/lib/compute/platform/intern/minio

lib/src/main/kotlin/org/veupathdb/lib/compute/platform/intern/minio/MinIOHax.kt

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,48 @@ import org.slf4j.Logger
44
import org.veupathdb.lib.s3.s34k.errors.S34KError
55
import org.veupathdb.lib.s3.s34k.objects.S3Object
66
import kotlin.time.Duration.Companion.milliseconds
7+
import kotlin.time.Duration.Companion.seconds
78

89
@Suppress("NOTHING_TO_INLINE")
910
internal object MinIOHax {
10-
var MaxDeleteAttempts = 5
11-
12-
var SleepMillis = 1_000L
13-
11+
/**
12+
* Maximum amount of time that the [delete] method should wait for an object's
13+
* deletion to be confirmed by MinIO.
14+
*/
15+
var MaxDeleteAwaitTime = 10.seconds
16+
17+
/**
18+
* Amount of time to sleep between MinIO API call retries.
19+
*/
20+
var RetrySleepTime = 1.seconds
21+
22+
/**
23+
* Max number of times an individual MinIO API call should be retried.
24+
*/
1425
var RetryCount = 3
1526

16-
fun sleepCountDuration(sleepCount: Int) = (sleepCount * SleepMillis).milliseconds
17-
27+
/**
28+
* Executes the given [action], retrying up to [RetryCount] times if the
29+
* call fails due to an error from MinIO.
30+
*
31+
* @param actionMsg Provider for a message describing the action being
32+
* performed. This will be called if necessary to write log lines.
33+
*
34+
* @param action MinIO interaction function to try to execute.
35+
*
36+
* @return The value returned by `action` on successful execution.
37+
*
38+
* @throws S34KError If the given [action] fails [RetryCount] times due to
39+
* MinIO errors. This exception will contain all MinIO exceptions thrown
40+
* during executions of the `action` function.
41+
*/
1842
context(log: Logger)
19-
fun <T> withRetries(actionMsg: () -> String, fn: () -> T) =
20-
withRetries(RetryCount, actionMsg, fn)
21-
22-
context(log: Logger)
23-
fun <T> withRetries(retries: Int, actionMsg: () -> String, fn: () -> T): T {
43+
fun <T> withRetries(actionMsg: () -> String, action: () -> T): T {
2444
var lastError: S34KError? = null
2545

26-
for (i in 1..retries) {
46+
for (i in 1..RetryCount) {
2747
try {
28-
return fn()
48+
return action()
2949
} catch (e: S34KError) {
3050
log.warn("failed {} time(s) to {}", i, actionMsg())
3151

@@ -42,33 +62,67 @@ internal object MinIOHax {
4262
throw lastError!!
4363
}
4464

65+
/**
66+
* Sleeps for the duration configured by [RetrySleepTime].
67+
*/
4568
context(log: Logger)
4669
fun sleep() {
47-
log.debug("sleeping for {}", { SleepMillis.milliseconds })
48-
Thread.sleep(SleepMillis)
70+
log.debug("sleeping for {}", { RetrySleepTime })
71+
Thread.sleep(RetrySleepTime.inWholeMilliseconds)
4972
}
5073

74+
/**
75+
* Convenience method for calling [delete] on an S3Object.
76+
*
77+
* @param obj Object to delete from MinIO.
78+
*/
5179
context(log: Logger)
5280
fun delete(obj: S3Object) = delete(obj.path, obj::delete, obj::exists)
5381

82+
/**
83+
* Tells MinIO to delete an object, then waits for MinIO to confirm the
84+
* object's deletion, sleeping for [RetrySleepTime] milliseconds between each
85+
* test for the target object's existence.
86+
*
87+
* This method wraps both the given [statFn] and [deleteFn] functions using
88+
* [withRetries] to retry all interactions with MinIO up to [RetryCount]
89+
* times.
90+
*
91+
* @param path Path of the object to be deleted. Used for logging.
92+
*
93+
* @param deleteFn Function to be called to delete the object from MinIO.
94+
*
95+
* @param statFn Function to be called to test if the object still exists in
96+
* MinIO.
97+
*
98+
* @throws S34KError If either of the given functions fail [RetryCount] times
99+
* due to MinIO errors. This exception will contain all MinIO exceptions
100+
* thrown during executions of the failing function.
101+
*/
54102
context(log: Logger)
55103
fun delete(path: String, deleteFn: () -> Unit, statFn: () -> Boolean) {
104+
val startTime = currentSystemMillis()
105+
var delta = 0.milliseconds
106+
56107
// Tell minio to delete the object
57-
deleteFn()
108+
withRetries({ "delete object $path" }, deleteFn)
58109

59-
// Sleep for a bit to let minio ponder the delete request
60-
sleep()
110+
// Sleep to let minio ponder the delete request
111+
while (delta < MaxDeleteAwaitTime) {
112+
sleep()
113+
delta = currentSystemMillis() - startTime
61114

62-
// If minio is being particularly dim, give it some more time to work it out
63-
for (i in 1..MaxDeleteAttempts) {
64-
if (!statFn())
115+
if (!withRetries({ "stat object $path" }, statFn))
65116
return
66117

67-
log.debug("waiting for object {} deletion: {}", path, sleepCountDuration(i))
68-
sleep()
118+
log.debug("waiting for object {} deletion: {}", path, delta)
69119
}
70120

71-
log.error("waited {} for object {} deletion, but MinIO reports that it still exists", sleepCountDuration(MaxDeleteAttempts), path)
121+
122+
log.error("waited {} for object {} deletion, but MinIO reports that it still exists", delta, path)
123+
72124
throw RuntimeException("object deletion timeout for MinIO object $path")
73125
}
126+
127+
private fun currentSystemMillis() = System.currentTimeMillis().milliseconds
74128
}

0 commit comments

Comments
 (0)