From 0159a35adf69cff8f222a92b1ed30414577af483 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sat, 15 Apr 2023 02:38:08 -0700
Subject: [PATCH 01/15] Network & API handler improvements
Improved Network connection handling via a connection read timeout, with exception handling
Improved API Response Handler - BufferedReader now reads the entire response string and checks whether it is null before assigning it to the 'timezone' variable
---
.gitignore | 9 +++++-
.idea/.gitignore | 3 ++
.../net/aboodyy/localtime/DateManager.java | 32 ++++++-------------
3 files changed, 21 insertions(+), 23 deletions(-)
create mode 100644 .idea/.gitignore
diff --git a/.gitignore b/.gitignore
index 744289d..7de4120 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,9 @@
# Project exclude paths
-/target/
\ No newline at end of file
+/target/
+.idea/compiler.xml
+.idea/discord.xml
+.idea/jarRepositories.xml
+.idea/misc.xml
+.idea/vcs.xml
+.idea/artifacts/Expansion_localtime.xml
+out/artifacts/Expansion_localtime/Expansion-localtime.jar
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 807f359..98a3dcf 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -1,23 +1,3 @@
-/*
-
- LocalTime Expansion - Provides PlaceholderAPI placeholders to give player's local time
- Copyright (C) 2020 aBooDyy
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
- */
-
package net.aboodyy.localtime;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
@@ -76,11 +56,19 @@ public void run() {
try {
URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
URLConnection connection = api.openConnection();
+ connection.setConnectTimeout(5000);
+ connection.setReadTimeout(5000);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- timezone = bufferedReader.readLine();
+ String response = bufferedReader.readLine();
+ if (response == null || response.isEmpty()) {
+ timezone = "undefined";
+ } else {
+ timezone = response.trim();
+ }
} catch (Exception e) {
timezone = "undefined";
+ Bukkit.getLogger().warning("[LocalTime] Failed to retrieve timezone for " + player.getName() + " from ipapi.co: " + e.getMessage());
}
if (timezone.equalsIgnoreCase("undefined")) {
@@ -104,4 +92,4 @@ public void clear() {
public void onLeave(PlayerQuitEvent e) {
timezones.remove(e.getPlayer().getUniqueId());
}
-}
+}
\ No newline at end of file
From f4a7aea05e8439506311de6ce93b4e469cbe975f Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sat, 15 Apr 2023 02:54:48 -0700
Subject: [PATCH 02/15] Implement retryDelay to DateManager constructor &
caching of players timezone via UUID
---
.../net/aboodyy/localtime/DateManager.java | 36 +++++++++++++------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 98a3dcf..b172deb 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -19,9 +19,13 @@
public class DateManager implements Listener {
private final Map timezones;
+ private final Map cache;
+ private int retryDelay = 0;
DateManager() {
- timezones = new HashMap<>();
+ this.timezones = new HashMap<>();
+ this.cache = new HashMap<>();
+ this.retryDelay = retryDelay;
}
public String getDate(String format, String timezone) {
@@ -35,16 +39,23 @@ public String getDate(String format, String timezone) {
public String getTimeZone(Player player) {
final String FAILED = "[LocalTime] Couldn't get " + player.getName() + "'s timezone. Will use default timezone.";
- String timezone = TimeZone.getDefault().getID();
+ String timezone = cache.get(player.getUniqueId().toString());
- if (timezones.containsKey(player.getUniqueId()))
- return timezones.get(player.getUniqueId());
+ if (timezone != null) {
+ return timezone;
+ }
+
+ timezone = timezones.get(player.getUniqueId());
+ if (timezone != null) {
+ return timezone;
+ }
InetSocketAddress address = player.getAddress();
- timezones.put(player.getUniqueId(), timezone);
+ timezone = TimeZone.getDefault().getID();
if (address == null) {
Bukkit.getLogger().info(FAILED);
+ cache.put(player.getUniqueId().toString(), timezone);
return timezone;
}
@@ -58,17 +69,18 @@ public void run() {
URLConnection connection = api.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- String response = bufferedReader.readLine();
- if (response == null || response.isEmpty()) {
+ timezone = bufferedReader.readLine();
+
+ if (timezone == null) {
timezone = "undefined";
} else {
- timezone = response.trim();
+ cache.put(player.getUniqueId().toString(), timezone);
}
} catch (Exception e) {
timezone = "undefined";
- Bukkit.getLogger().warning("[LocalTime] Failed to retrieve timezone for " + player.getName() + " from ipapi.co: " + e.getMessage());
}
if (timezone.equalsIgnoreCase("undefined")) {
@@ -80,16 +92,18 @@ public void run() {
}
}.runTaskAsynchronously(PlaceholderAPIPlugin.getInstance());
- return timezones.get(player.getUniqueId());
+ return timezone;
}
public void clear() {
timezones.clear();
+ cache.clear();
}
@SuppressWarnings("unused")
@EventHandler
public void onLeave(PlayerQuitEvent e) {
timezones.remove(e.getPlayer().getUniqueId());
+ cache.remove(e.getPlayer().getUniqueId().toString());
}
-}
\ No newline at end of file
+}
From c84f4a6f4a36d215362beae9f42159c88980eedd Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sat, 15 Apr 2023 03:02:41 -0700
Subject: [PATCH 03/15] Implement BukkitRunnable task for retryDelay
When the API call fails, added a new BukkitRunnable that will be scheduled to run after the retryDelay. It will retry adding the timezone to the map after the delay instead of adding it immediately. This way, we prevent overloading the API
---
src/main/java/net/aboodyy/localtime/DateManager.java | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index b172deb..8a52b1b 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -20,7 +20,7 @@ public class DateManager implements Listener {
private final Map timezones;
private final Map cache;
- private int retryDelay = 0;
+ private int retryDelay;
DateManager() {
this.timezones = new HashMap<>();
@@ -86,6 +86,14 @@ public void run() {
if (timezone.equalsIgnoreCase("undefined")) {
Bukkit.getLogger().info(FAILED);
timezone = TimeZone.getDefault().getID();
+ String finalTimezone = timezone;
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ timezones.put(player.getUniqueId(), finalTimezone);
+ }
+ }.runTaskLaterAsynchronously(PlaceholderAPIPlugin.getInstance(), retryDelay);
+ return;
}
timezones.put(player.getUniqueId(), timezone);
From 559f24ee5156fe7b629cc1a1351bae28259df096 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sat, 15 Apr 2023 03:22:15 -0700
Subject: [PATCH 04/15] rUnNaBLE bAd
getTimeZone now uses a new thread instead of a BukkitRunnable to handle the API request
---
.../net/aboodyy/localtime/DateManager.java | 66 ++++++++-----------
1 file changed, 27 insertions(+), 39 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 8a52b1b..e7a89d3 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -1,12 +1,10 @@
package net.aboodyy.localtime;
-import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
-import org.bukkit.scheduler.BukkitRunnable;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@@ -22,7 +20,7 @@ public class DateManager implements Listener {
private final Map cache;
private int retryDelay;
- DateManager() {
+ public DateManager() {
this.timezones = new HashMap<>();
this.cache = new HashMap<>();
this.retryDelay = retryDelay;
@@ -59,46 +57,36 @@ public String getTimeZone(Player player) {
return timezone;
}
- new BukkitRunnable() {
- @Override
- public void run() {
- String timezone;
-
- try {
- URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
- URLConnection connection = api.openConnection();
- connection.setConnectTimeout(5000);
- connection.setReadTimeout(5000);
- connection.setRequestProperty("User-Agent", "Mozilla/5.0");
-
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- timezone = bufferedReader.readLine();
-
- if (timezone == null) {
- timezone = "undefined";
- } else {
- cache.put(player.getUniqueId().toString(), timezone);
- }
- } catch (Exception e) {
- timezone = "undefined";
- }
+ String finalTimezone = timezone;
+ new Thread(() -> {
+ String timeZone;
+
+ try {
+ URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
+ URLConnection connection = api.openConnection();
+ connection.setConnectTimeout(5000);
+ connection.setReadTimeout(5000);
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0");
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ timeZone = bufferedReader.readLine();
- if (timezone.equalsIgnoreCase("undefined")) {
- Bukkit.getLogger().info(FAILED);
- timezone = TimeZone.getDefault().getID();
- String finalTimezone = timezone;
- new BukkitRunnable() {
- @Override
- public void run() {
- timezones.put(player.getUniqueId(), finalTimezone);
- }
- }.runTaskLaterAsynchronously(PlaceholderAPIPlugin.getInstance(), retryDelay);
- return;
+ if (timeZone == null) {
+ timeZone = "undefined";
+ } else {
+ cache.put(player.getUniqueId().toString(), timeZone);
}
+ } catch (Exception e) {
+ timeZone = "undefined";
+ }
- timezones.put(player.getUniqueId(), timezone);
+ if (timeZone.equalsIgnoreCase("undefined")) {
+ Bukkit.getLogger().info(FAILED);
+ timeZone = finalTimezone;
}
- }.runTaskAsynchronously(PlaceholderAPIPlugin.getInstance());
+
+ timezones.put(player.getUniqueId(), timeZone);
+ }).start();
return timezone;
}
From c584e27af5b626a1b1c723c6d68b1f800da1a915 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sun, 16 Apr 2023 00:04:51 -0700
Subject: [PATCH 05/15] Append license info
---
.../java/net/aboodyy/localtime/DateManager.java | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index e7a89d3..1fd6ea0 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -1,3 +1,18 @@
+/*
+ LocalTime Expansion - Provides PlaceholderAPI placeholders to give player's local time
+ Copyright (C) 2020 aBooDyy
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
package net.aboodyy.localtime;
import org.bukkit.Bukkit;
From 82ca41bea627c3082bc93bf4eaa5f3c152395f7e Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sun, 16 Apr 2023 00:26:17 -0700
Subject: [PATCH 06/15] Code fixes
Integrated 'ConcurrentHashMap' in place of 'Hashmap' to ensure the expansion is thread-safe
retryDelay was also migrated to a new 'getTimeZoneFromAPI' method, and appropriately initialized
---
.../net/aboodyy/localtime/DateManager.java | 38 ++++++++++++-------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 1fd6ea0..6c0df13 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -28,6 +28,8 @@
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
public class DateManager implements Listener {
@@ -38,7 +40,7 @@ public class DateManager implements Listener {
public DateManager() {
this.timezones = new HashMap<>();
this.cache = new HashMap<>();
- this.retryDelay = retryDelay;
+ this.retryDelay = 5; // default to 5 seconds
}
public String getDate(String format, String timezone) {
@@ -72,9 +74,8 @@ public String getTimeZone(Player player) {
return timezone;
}
- String finalTimezone = timezone;
- new Thread(() -> {
- String timeZone;
+ CompletableFuture futureTimezone = CompletableFuture.supplyAsync(() -> {
+ String result = "undefined";
try {
URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
@@ -84,26 +85,34 @@ public String getTimeZone(Player player) {
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- timeZone = bufferedReader.readLine();
+ result = bufferedReader.readLine();
- if (timeZone == null) {
- timeZone = "undefined";
+ if (result == null) {
+ result = "undefined";
} else {
- cache.put(player.getUniqueId().toString(), timeZone);
+ cache.put(player.getUniqueId().toString(), result);
}
} catch (Exception e) {
- timeZone = "undefined";
+ result = "undefined";
}
- if (timeZone.equalsIgnoreCase("undefined")) {
+ if (result.equalsIgnoreCase("undefined")) {
Bukkit.getLogger().info(FAILED);
- timeZone = finalTimezone;
+ result = TimeZone.getDefault().getID();
}
- timezones.put(player.getUniqueId(), timeZone);
- }).start();
+ timezones.put(player.getUniqueId(), result);
+ return result;
+ });
- return timezone;
+ try {
+ return futureTimezone.get(retryDelay, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
+ cache.put(player.getUniqueId().toString(), timezone);
+ timezones.put(player.getUniqueId(), timezone);
+ return timezone;
+ }
}
public void clear() {
@@ -117,4 +126,5 @@ public void onLeave(PlayerQuitEvent e) {
timezones.remove(e.getPlayer().getUniqueId());
cache.remove(e.getPlayer().getUniqueId().toString());
}
+
}
From 66cd5a9a33392ed4489cfcb9f3b91537a2117227 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sun, 16 Apr 2023 01:46:58 -0700
Subject: [PATCH 07/15] Oops
---
.../net/aboodyy/localtime/DateManager.java | 43 +++++++++++++------
1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 6c0df13..cbcaec1 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -27,20 +27,31 @@
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
public class DateManager implements Listener {
private final Map timezones;
private final Map cache;
+ private final ScheduledExecutorService executorService;
+ private final ConcurrentHashMap concurrentTimezones;
+ private final ConcurrentHashMap concurrentCache;
private int retryDelay;
public DateManager() {
- this.timezones = new HashMap<>();
- this.cache = new HashMap<>();
+ this.concurrentTimezones = new ConcurrentHashMap<>();
+ this.concurrentCache = new ConcurrentHashMap<>();
this.retryDelay = 5; // default to 5 seconds
+ this.executorService = Executors.newSingleThreadScheduledExecutor();
+ this.timezones = concurrentTimezones;
+ this.cache = concurrentCache;
}
public String getDate(String format, String timezone) {
@@ -74,6 +85,7 @@ public String getTimeZone(Player player) {
return timezone;
}
+ final String timezoneFinal = timezone;
CompletableFuture futureTimezone = CompletableFuture.supplyAsync(() -> {
String result = "undefined";
@@ -98,21 +110,21 @@ public String getTimeZone(Player player) {
if (result.equalsIgnoreCase("undefined")) {
Bukkit.getLogger().info(FAILED);
- result = TimeZone.getDefault().getID();
+ result = timezoneFinal;
}
timezones.put(player.getUniqueId(), result);
return result;
+ }, executorService);
+
+ futureTimezone.exceptionally(ex -> {
+ Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage());
+ cache.put(player.getUniqueId().toString(), timezoneFinal);
+ timezones.put(player.getUniqueId(), timezoneFinal);
+ return timezoneFinal;
});
- try {
- return futureTimezone.get(retryDelay, TimeUnit.SECONDS);
- } catch (Exception e) {
- Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
- cache.put(player.getUniqueId().toString(), timezone);
- timezones.put(player.getUniqueId(), timezone);
- return timezone;
- }
+ return timezoneFinal;
}
public void clear() {
@@ -127,4 +139,9 @@ public void onLeave(PlayerQuitEvent e) {
cache.remove(e.getPlayer().getUniqueId().toString());
}
+ public void setRetryDelay(int delay) {
+ this.retryDelay = delay;
+ }
}
+
+
From 7b848bd62797e43de7806fb75c7a58ca2b39fd13 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Sun, 16 Apr 2023 01:59:16 -0700
Subject: [PATCH 08/15] Oops Pt. 2
I really need to sleep...
---
.../net/aboodyy/localtime/DateManager.java | 44 +++++++++++--------
1 file changed, 25 insertions(+), 19 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index cbcaec1..9c6b670 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -88,24 +88,32 @@ public String getTimeZone(Player player) {
final String timezoneFinal = timezone;
CompletableFuture futureTimezone = CompletableFuture.supplyAsync(() -> {
String result = "undefined";
-
- try {
- URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
- URLConnection connection = api.openConnection();
- connection.setConnectTimeout(5000);
- connection.setReadTimeout(5000);
- connection.setRequestProperty("User-Agent", "Mozilla/5.0");
-
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- result = bufferedReader.readLine();
-
- if (result == null) {
+ int retries = 3;
+
+ while (retries-- > 0) {
+ try {
+ URL api = new URL("https://ipapi.co/" + address.getAddress().getHostAddress() + "/timezone/");
+ URLConnection connection = api.openConnection();
+ connection.setConnectTimeout(5000);
+ connection.setReadTimeout(5000);
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0");
+
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ result = bufferedReader.readLine();
+
+ if (result == null) {
+ result = "undefined";
+ } else {
+ cache.put(player.getUniqueId().toString(), result);
+ }
+ break; // exit loop if successful
+ } catch (Exception e) {
result = "undefined";
- } else {
- cache.put(player.getUniqueId().toString(), result);
+ Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
+ try {
+ Thread.sleep(retryDelay * 1000);
+ } catch (InterruptedException ignored) {}
}
- } catch (Exception e) {
- result = "undefined";
}
if (result.equalsIgnoreCase("undefined")) {
@@ -117,6 +125,7 @@ public String getTimeZone(Player player) {
return result;
}, executorService);
+
futureTimezone.exceptionally(ex -> {
Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage());
cache.put(player.getUniqueId().toString(), timezoneFinal);
@@ -139,9 +148,6 @@ public void onLeave(PlayerQuitEvent e) {
cache.remove(e.getPlayer().getUniqueId().toString());
}
- public void setRetryDelay(int delay) {
- this.retryDelay = delay;
- }
}
From 2be67a21420c0bc465a33ecf8fe99de697ee2542 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Wed, 19 Apr 2023 00:30:08 -0700
Subject: [PATCH 09/15] Enhance DateManager and LocalTimeExpansion classes
Implement cache expiration in DateManager
Optimize cache structure in DateManager
Return CompletableFuture in DateManager's getTimeZone
Adapt LocalTimeExpansion to work with updated DateManager
---
.../net/aboodyy/localtime/DateManager.java | 68 +++++++++++++------
.../aboodyy/localtime/LocalTimeExpansion.java | 18 +++--
2 files changed, 59 insertions(+), 27 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 9c6b670..7338348 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -1,16 +1,21 @@
/*
+
LocalTime Expansion - Provides PlaceholderAPI placeholders to give player's local time
Copyright (C) 2020 aBooDyy
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
+
You should have received a copy of the GNU General Public License
along with this program. If not, see .
+
*/
package net.aboodyy.localtime;
@@ -41,17 +46,14 @@ public class DateManager implements Listener {
private final Map timezones;
private final Map cache;
private final ScheduledExecutorService executorService;
- private final ConcurrentHashMap concurrentTimezones;
- private final ConcurrentHashMap concurrentCache;
private int retryDelay;
+ private final int cacheExpirationMinutes = 1440; // Cache entries expire after 1440 minutes (1 Day)
public DateManager() {
- this.concurrentTimezones = new ConcurrentHashMap<>();
- this.concurrentCache = new ConcurrentHashMap<>();
+ this.timezones = new ConcurrentHashMap<>();
+ this.cache = new ConcurrentHashMap<>();
this.retryDelay = 5; // default to 5 seconds
this.executorService = Executors.newSingleThreadScheduledExecutor();
- this.timezones = concurrentTimezones;
- this.cache = concurrentCache;
}
public String getDate(String format, String timezone) {
@@ -63,17 +65,36 @@ public String getDate(String format, String timezone) {
return dateFormat.format(date);
}
- public String getTimeZone(Player player) {
+ private boolean isCacheExpired(UUID uuid) {
+ String timestampStr = cache.get(uuid.toString() + "_timestamp");
+ if (timestampStr == null) {
+ return true;
+ }
+
+ long timestamp = Long.parseLong(timestampStr);
+ long currentTime = System.currentTimeMillis();
+ long expirationTime = cacheExpirationMinutes * 60 * 1000;
+
+ return (currentTime - timestamp) >= expirationTime;
+ }
+
+ public CompletableFuture getTimeZone(Player player) {
final String FAILED = "[LocalTime] Couldn't get " + player.getName() + "'s timezone. Will use default timezone.";
- String timezone = cache.get(player.getUniqueId().toString());
- if (timezone != null) {
- return timezone;
+ String cachedTimezone = cache.get(player.getUniqueId().toString());
+ if (cachedTimezone != null) {
+ // If the cached timezone is not expired, return it
+ if (!isCacheExpired(player.getUniqueId())) {
+ return CompletableFuture.completedFuture(cachedTimezone);
+ } else {
+ // If the cached timezone is expired, remove it from the cache
+ cache.remove(player.getUniqueId().toString());
+ }
}
- timezone = timezones.get(player.getUniqueId());
+ String timezone = timezones.get(player.getUniqueId());
if (timezone != null) {
- return timezone;
+ return CompletableFuture.completedFuture(timezone);
}
InetSocketAddress address = player.getAddress();
@@ -82,7 +103,7 @@ public String getTimeZone(Player player) {
if (address == null) {
Bukkit.getLogger().info(FAILED);
cache.put(player.getUniqueId().toString(), timezone);
- return timezone;
+ return CompletableFuture.completedFuture(timezone);
}
final String timezoneFinal = timezone;
@@ -98,15 +119,18 @@ public String getTimeZone(Player player) {
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- result = bufferedReader.readLine();
-
- if (result == null) {
- result = "undefined";
- } else {
- cache.put(player.getUniqueId().toString(), result);
+ // Use try-with-resources to automatically close the BufferedReader
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
+ result = bufferedReader.readLine();
+
+ if (result == null) {
+ result = "undefined";
+ } else {
+ cache.put(player.getUniqueId().toString(), result);
+ cache.put(player.getUniqueId().toString() + "_timestamp", String.valueOf(System.currentTimeMillis()));
+ }
+ break; // exit loop if successful
}
- break; // exit loop if successful
} catch (Exception e) {
result = "undefined";
Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
@@ -133,7 +157,7 @@ public String getTimeZone(Player player) {
return timezoneFinal;
});
- return timezoneFinal;
+ return CompletableFuture.completedFuture(timezoneFinal);
}
public void clear() {
diff --git a/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java b/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
index 8e39d46..0fb475f 100644
--- a/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
+++ b/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
@@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
@SuppressWarnings("unused")
public class LocalTimeExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
@@ -43,12 +44,12 @@ public String getIdentifier() {
@Override
public String getAuthor() {
- return "aBooDyy";
+ return "aBooDyy, Opal";
}
@Override
public String getVersion() {
- return "1.2";
+ return "1.3";
}
@Override
@@ -82,7 +83,10 @@ public String onPlaceholderRequest(Player p, String identifier) {
args = identifier.split("time_");
if (args.length < 2) return null;
- return dateManager.getDate(args[1], dateManager.getTimeZone(p));
+ CompletableFuture timezoneFuture = dateManager.getTimeZone(p);
+ String timezone = timezoneFuture.join();
+
+ return dateManager.getDate(args[1], timezone);
}
if (identifier.startsWith("timezone_")) {
@@ -99,8 +103,12 @@ public String onPlaceholderRequest(Player p, String identifier) {
return dateManager.getDate(format, args[1]);
}
- if (identifier.equalsIgnoreCase("time"))
- return dateManager.getDate(format, dateManager.getTimeZone(p));
+ if (identifier.equalsIgnoreCase("time")) {
+ CompletableFuture timezoneFuture = dateManager.getTimeZone(p);
+ String timezone = timezoneFuture.join();
+
+ return dateManager.getDate(format, timezone);
+ }
return null;
}
From a4cdbdf2d4a82f60cca68d95bd103e99c4bc258b Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Tue, 25 Apr 2023 02:17:42 -0700
Subject: [PATCH 10/15] Refactor DateManager: separate cache expiry, data
removal, and improve efficiency
Remove cache expiry checks from getTimeZone method
Remove data removal from onLeave event handler
Create a new scheduled task removeExpiredEntries to handle cache expiry and player data removal
Update isCacheExpired method to remove players from the timezones map when cache expires
Add a check in removeExpiredEntries to skip non-UUID keys in the cache
Remove unnecessary onLeave event handler and Listener implementation
---
.../net/aboodyy/localtime/DateManager.java | 52 +++++++++++--------
1 file changed, 30 insertions(+), 22 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 7338348..21d663e 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -22,9 +22,7 @@
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
-import org.bukkit.event.player.PlayerQuitEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
@@ -36,10 +34,7 @@
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.*;
public class DateManager implements Listener {
@@ -54,6 +49,8 @@ public DateManager() {
this.cache = new ConcurrentHashMap<>();
this.retryDelay = 5; // default to 5 seconds
this.executorService = Executors.newSingleThreadScheduledExecutor();
+
+ executorService.scheduleAtFixedRate(this::removeExpiredEntries, cacheExpirationMinutes, cacheExpirationMinutes, TimeUnit.MINUTES);
}
public String getDate(String format, String timezone) {
@@ -75,7 +72,32 @@ private boolean isCacheExpired(UUID uuid) {
long currentTime = System.currentTimeMillis();
long expirationTime = cacheExpirationMinutes * 60 * 1000;
- return (currentTime - timestamp) >= expirationTime;
+ if ((currentTime - timestamp) >= expirationTime) {
+ timezones.remove(uuid); // Remove the player from the timezones map when cache expires
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void removeExpiredEntries() {
+ for (Map.Entry entry : cache.entrySet()) {
+ if (entry.getKey().endsWith("_timestamp")) {
+ continue; // Skip keys with the "_timestamp" suffix
+ }
+
+ UUID uuid;
+ try {
+ uuid = UUID.fromString(entry.getKey());
+ } catch (IllegalArgumentException e) {
+ continue; // Skip non-UUID keys
+ }
+
+ if (isCacheExpired(uuid)) {
+ cache.remove(uuid.toString());
+ timezones.remove(uuid);
+ }
+ }
}
public CompletableFuture getTimeZone(Player player) {
@@ -83,13 +105,7 @@ public CompletableFuture getTimeZone(Player player) {
String cachedTimezone = cache.get(player.getUniqueId().toString());
if (cachedTimezone != null) {
- // If the cached timezone is not expired, return it
- if (!isCacheExpired(player.getUniqueId())) {
- return CompletableFuture.completedFuture(cachedTimezone);
- } else {
- // If the cached timezone is expired, remove it from the cache
- cache.remove(player.getUniqueId().toString());
- }
+ return CompletableFuture.completedFuture(cachedTimezone);
}
String timezone = timezones.get(player.getUniqueId());
@@ -164,14 +180,6 @@ public void clear() {
timezones.clear();
cache.clear();
}
-
- @SuppressWarnings("unused")
- @EventHandler
- public void onLeave(PlayerQuitEvent e) {
- timezones.remove(e.getPlayer().getUniqueId());
- cache.remove(e.getPlayer().getUniqueId().toString());
- }
-
}
From ef50f5d249e3eefacc21cfddc9e4b945c7857626 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Fri, 5 May 2023 23:14:27 -0700
Subject: [PATCH 11/15] gitignore
---
.gitignore | 10 ++--------
.idea/.gitignore | 3 ---
pom.xml | 2 +-
3 files changed, 3 insertions(+), 12 deletions(-)
delete mode 100644 .idea/.gitignore
diff --git a/.gitignore b/.gitignore
index 7de4120..c63e02c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,3 @@
-# Project exclude paths
/target/
-.idea/compiler.xml
-.idea/discord.xml
-.idea/jarRepositories.xml
-.idea/misc.xml
-.idea/vcs.xml
-.idea/artifacts/Expansion_localtime.xml
-out/artifacts/Expansion_localtime/Expansion-localtime.jar
+.idea/**
+out/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/pom.xml b/pom.xml
index 57aa9a4..5ce75b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
net.aboodyy
localtime-expansion
- 1.2
+ 1.3
From 89c3913c1db7f11603a53d10410284ce5d058feb Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Fri, 14 Jul 2023 05:21:53 -0700
Subject: [PATCH 12/15] Replace ConcurrentHashmap with Guava's Cache
---
.../net/aboodyy/localtime/DateManager.java | 59 ++++---------------
1 file changed, 10 insertions(+), 49 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 21d663e..102f4aa 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -20,6 +20,9 @@
package net.aboodyy.localtime;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
@@ -39,18 +42,18 @@
public class DateManager implements Listener {
private final Map timezones;
- private final Map cache;
+ private final Cache cache;
private final ScheduledExecutorService executorService;
private int retryDelay;
private final int cacheExpirationMinutes = 1440; // Cache entries expire after 1440 minutes (1 Day)
public DateManager() {
this.timezones = new ConcurrentHashMap<>();
- this.cache = new ConcurrentHashMap<>();
+ this.cache = CacheBuilder.newBuilder()
+ .expireAfterWrite(cacheExpirationMinutes, TimeUnit.MINUTES)
+ .build();
this.retryDelay = 5; // default to 5 seconds
this.executorService = Executors.newSingleThreadScheduledExecutor();
-
- executorService.scheduleAtFixedRate(this::removeExpiredEntries, cacheExpirationMinutes, cacheExpirationMinutes, TimeUnit.MINUTES);
}
public String getDate(String format, String timezone) {
@@ -62,48 +65,10 @@ public String getDate(String format, String timezone) {
return dateFormat.format(date);
}
- private boolean isCacheExpired(UUID uuid) {
- String timestampStr = cache.get(uuid.toString() + "_timestamp");
- if (timestampStr == null) {
- return true;
- }
-
- long timestamp = Long.parseLong(timestampStr);
- long currentTime = System.currentTimeMillis();
- long expirationTime = cacheExpirationMinutes * 60 * 1000;
-
- if ((currentTime - timestamp) >= expirationTime) {
- timezones.remove(uuid); // Remove the player from the timezones map when cache expires
- return true;
- } else {
- return false;
- }
- }
-
- private void removeExpiredEntries() {
- for (Map.Entry entry : cache.entrySet()) {
- if (entry.getKey().endsWith("_timestamp")) {
- continue; // Skip keys with the "_timestamp" suffix
- }
-
- UUID uuid;
- try {
- uuid = UUID.fromString(entry.getKey());
- } catch (IllegalArgumentException e) {
- continue; // Skip non-UUID keys
- }
-
- if (isCacheExpired(uuid)) {
- cache.remove(uuid.toString());
- timezones.remove(uuid);
- }
- }
- }
-
public CompletableFuture getTimeZone(Player player) {
final String FAILED = "[LocalTime] Couldn't get " + player.getName() + "'s timezone. Will use default timezone.";
- String cachedTimezone = cache.get(player.getUniqueId().toString());
+ String cachedTimezone = cache.getIfPresent(player.getUniqueId().toString());
if (cachedTimezone != null) {
return CompletableFuture.completedFuture(cachedTimezone);
}
@@ -143,7 +108,6 @@ public CompletableFuture getTimeZone(Player player) {
result = "undefined";
} else {
cache.put(player.getUniqueId().toString(), result);
- cache.put(player.getUniqueId().toString() + "_timestamp", String.valueOf(System.currentTimeMillis()));
}
break; // exit loop if successful
}
@@ -165,7 +129,6 @@ public CompletableFuture getTimeZone(Player player) {
return result;
}, executorService);
-
futureTimezone.exceptionally(ex -> {
Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage());
cache.put(player.getUniqueId().toString(), timezoneFinal);
@@ -178,8 +141,6 @@ public CompletableFuture getTimeZone(Player player) {
public void clear() {
timezones.clear();
- cache.clear();
+ cache.invalidateAll();
}
-}
-
-
+}
\ No newline at end of file
From 64933bb55d3056ad57c25bbf61d05aebcd19a669 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Fri, 14 Jul 2023 05:37:48 -0700
Subject: [PATCH 13/15] Use PAPI's logger instead of Bukkit's
---
src/main/java/net/aboodyy/localtime/DateManager.java | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 102f4aa..3305c67 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -22,8 +22,7 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
-
-import org.bukkit.Bukkit;
+import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
@@ -38,6 +37,7 @@
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.*;
+import java.util.logging.Level;
public class DateManager implements Listener {
@@ -82,7 +82,7 @@ public CompletableFuture getTimeZone(Player player) {
timezone = TimeZone.getDefault().getID();
if (address == null) {
- Bukkit.getLogger().info(FAILED);
+ PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
cache.put(player.getUniqueId().toString(), timezone);
return CompletableFuture.completedFuture(timezone);
}
@@ -113,7 +113,7 @@ public CompletableFuture getTimeZone(Player player) {
}
} catch (Exception e) {
result = "undefined";
- Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage());
+ PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + e.getMessage(), e);
try {
Thread.sleep(retryDelay * 1000);
} catch (InterruptedException ignored) {}
@@ -121,7 +121,7 @@ public CompletableFuture getTimeZone(Player player) {
}
if (result.equalsIgnoreCase("undefined")) {
- Bukkit.getLogger().info(FAILED);
+ PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
result = timezoneFinal;
}
@@ -130,7 +130,7 @@ public CompletableFuture getTimeZone(Player player) {
}, executorService);
futureTimezone.exceptionally(ex -> {
- Bukkit.getLogger().warning("[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage());
+ PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage(), ex);
cache.put(player.getUniqueId().toString(), timezoneFinal);
timezones.put(player.getUniqueId(), timezoneFinal);
return timezoneFinal;
From e6466fdc71da81e7f3fb177b2e1dfb9f63ccd87a Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Fri, 14 Jul 2023 05:49:36 -0700
Subject: [PATCH 14/15] Fixes & Improvements
`Shutdown` method to shut down the executor service on `clear()`
Fixed `getTimeZone` method to be non-blocking
Removed premature return of `CompletableFuture`
---
.../net/aboodyy/localtime/DateManager.java | 23 +++++++++++--------
.../aboodyy/localtime/LocalTimeExpansion.java | 1 +
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 3305c67..5b9b99a 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -79,15 +79,15 @@ public CompletableFuture getTimeZone(Player player) {
}
InetSocketAddress address = player.getAddress();
- timezone = TimeZone.getDefault().getID();
-
if (address == null) {
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
+ timezone = TimeZone.getDefault().getID();
cache.put(player.getUniqueId().toString(), timezone);
return CompletableFuture.completedFuture(timezone);
}
- final String timezoneFinal = timezone;
+ final String defaultTimezone = TimeZone.getDefault().getID();
+
CompletableFuture futureTimezone = CompletableFuture.supplyAsync(() -> {
String result = "undefined";
int retries = 3;
@@ -100,7 +100,6 @@ public CompletableFuture getTimeZone(Player player) {
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
- // Use try-with-resources to automatically close the BufferedReader
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
result = bufferedReader.readLine();
@@ -109,7 +108,7 @@ public CompletableFuture getTimeZone(Player player) {
} else {
cache.put(player.getUniqueId().toString(), result);
}
- break; // exit loop if successful
+ break;
}
} catch (Exception e) {
result = "undefined";
@@ -122,7 +121,7 @@ public CompletableFuture getTimeZone(Player player) {
if (result.equalsIgnoreCase("undefined")) {
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, FAILED);
- result = timezoneFinal;
+ result = defaultTimezone;
}
timezones.put(player.getUniqueId(), result);
@@ -131,16 +130,20 @@ public CompletableFuture getTimeZone(Player player) {
futureTimezone.exceptionally(ex -> {
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "[LocalTime] Exception while getting timezone for player " + player.getName() + ": " + ex.getMessage(), ex);
- cache.put(player.getUniqueId().toString(), timezoneFinal);
- timezones.put(player.getUniqueId(), timezoneFinal);
- return timezoneFinal;
+ cache.put(player.getUniqueId().toString(), defaultTimezone);
+ timezones.put(player.getUniqueId(), defaultTimezone);
+ return defaultTimezone;
});
- return CompletableFuture.completedFuture(timezoneFinal);
+ return futureTimezone;
}
public void clear() {
timezones.clear();
cache.invalidateAll();
}
+
+ public void shutdown() {
+ this.executorService.shutdown();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java b/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
index 0fb475f..ad62388 100644
--- a/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
+++ b/src/main/java/net/aboodyy/localtime/LocalTimeExpansion.java
@@ -70,6 +70,7 @@ public Map getDefaults() {
public void clear() {
dateManager.clear();
HandlerList.unregisterAll(dateManager);
+ dateManager.shutdown();
}
@Override
From d612105b7a684e8e238c7e05dcd432a6bc134b09 Mon Sep 17 00:00:00 2001
From: Opal <58598304+Opalinium@users.noreply.github.com>
Date: Fri, 14 Jul 2023 17:45:11 -0700
Subject: [PATCH 15/15] Consolidate expireAfterWrite duration
---
src/main/java/net/aboodyy/localtime/DateManager.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/main/java/net/aboodyy/localtime/DateManager.java b/src/main/java/net/aboodyy/localtime/DateManager.java
index 5b9b99a..693f61a 100644
--- a/src/main/java/net/aboodyy/localtime/DateManager.java
+++ b/src/main/java/net/aboodyy/localtime/DateManager.java
@@ -45,12 +45,11 @@ public class DateManager implements Listener {
private final Cache cache;
private final ScheduledExecutorService executorService;
private int retryDelay;
- private final int cacheExpirationMinutes = 1440; // Cache entries expire after 1440 minutes (1 Day)
public DateManager() {
this.timezones = new ConcurrentHashMap<>();
this.cache = CacheBuilder.newBuilder()
- .expireAfterWrite(cacheExpirationMinutes, TimeUnit.MINUTES)
+ .expireAfterWrite(1, TimeUnit.DAYS)
.build();
this.retryDelay = 5; // default to 5 seconds
this.executorService = Executors.newSingleThreadScheduledExecutor();