From f6b4792fba253236241eb8b7a24f4cb2b680d8c7 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 26 Oct 2024 01:27:33 +1100 Subject: [PATCH 1/2] Update OffshoreInstance.java --- .../discord/util/offshore/OffshoreInstance.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/link/locutus/discord/util/offshore/OffshoreInstance.java b/src/main/java/link/locutus/discord/util/offshore/OffshoreInstance.java index 5a9d40e3..8c80f960 100644 --- a/src/main/java/link/locutus/discord/util/offshore/OffshoreInstance.java +++ b/src/main/java/link/locutus/discord/util/offshore/OffshoreInstance.java @@ -1539,10 +1539,18 @@ public TransferResult transferUnsafe2(Auth auth, NationOrAlliance receiver, Map< } private TransferResult createTransfer(PoliticsAndWarV3 api, NationOrAlliance receiver, Map transfer, String note) { - Bankrec result = api.transferFromBank(ResourceType.resourcesToArray(transfer), receiver, note); - double[] amt = ResourceType.fromApiV3(result, ResourceType.getBuffer()); - String amtStr = ResourceType.resourcesToString(amt); - return new TransferResult(TransferStatus.SUCCESS, receiver, amt, note).addMessage("Success: " + amtStr); + try { + Bankrec result = api.transferFromBank(ResourceType.resourcesToArray(transfer), receiver, note); + double[] amt = ResourceType.fromApiV3(result, ResourceType.getBuffer()); + String amtStr = ResourceType.resourcesToString(amt); + return new TransferResult(TransferStatus.SUCCESS, receiver, amt, note).addMessage("Success: " + amtStr); + } catch (HttpClientErrorException.Unauthorized e) { + return new TransferResult(TransferStatus.INVALID_API_KEY, receiver, transfer, note).addMessage("Invalid API key"); + } catch (RuntimeException e) { + e.printStackTrace(); + String msg = e.getMessage(); + return categorize(receiver, transfer, note, StringMan.stripApiKey(msg)); + } } public TransferResult transferUnsafe(Auth auth, NationOrAlliance receiver, Map transfer, String note) { From 3499c79373ee03f96c954c8cdbd432f418799019 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 26 Oct 2024 15:24:46 +1100 Subject: [PATCH 2/2] Cache rads --- .../impl/pw/commands/CustomSheetCommands.java | 18 +++-- .../link/locutus/discord/db/NationDB.java | 18 ++++- .../locutus/discord/util/sheet/GoogleDoc.java | 2 +- .../discord/util/sheet/SpreadSheet.java | 72 +++++++++++++------ 4 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/CustomSheetCommands.java b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/CustomSheetCommands.java index c49bc15c..147e79cf 100644 --- a/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/CustomSheetCommands.java +++ b/src/main/java/link/locutus/discord/commands/manager/v2/impl/pw/commands/CustomSheetCommands.java @@ -390,11 +390,12 @@ public String auto(ValueStore store, @Me GuildDB db, SpreadSheet sheet, @Switch( Map> customTabs = new LinkedHashMap<>(); Map tabs = sheet.fetchTabs(); + + + Map customTabsToFetch = new LinkedHashMap<>(); for (Map.Entry entry : tabs.entrySet()) { String tabName = entry.getValue(); SelectionAlias selection; - SheetTemplate template = null; - try { selection = SheetBindings.selectionAlias(true, manager, store, tabName); } catch (IllegalArgumentException e) { @@ -446,11 +447,19 @@ public String auto(ValueStore store, @Me GuildDB db, SpreadSheet sheet, @Switch( continue; } } + customTabsToFetch.put(tabName, selection); + } + + Map>> headerRows = sheet.fetchHeaderRows(customTabsToFetch.keySet()); + for (Map.Entry>> entry : headerRows.entrySet()) { + String tabName = entry.getKey(); + SelectionAlias selection = customTabsToFetch.get(tabName); Placeholders ph = phMap.get(selection.getType()); - List> row = sheet.fetchRange(tabName, "1:1"); + List> row = entry.getValue(); List header = row == null || row.isEmpty() ? null : row.get(0).stream().map(o -> o == null ? "" : o.toString()).toList(); + SheetTemplate template = null; if (header == null || header.isEmpty()) { errors.add("Tab `" + tabName + "` has no header row"); } else { @@ -460,9 +469,10 @@ public String auto(ValueStore store, @Me GuildDB db, SpreadSheet sheet, @Switch( if (template == null) { continue; } - customTabs.put(tabName, Map.entry(selection, template)); } + + if (customTabs.isEmpty()) { errors.add("No tabs found. No tabs will be updated"); return "**Result**:\n- " + StringMan.join(errors, "\n- "); diff --git a/src/main/java/link/locutus/discord/db/NationDB.java b/src/main/java/link/locutus/discord/db/NationDB.java index 957dc593..2194aa07 100644 --- a/src/main/java/link/locutus/discord/db/NationDB.java +++ b/src/main/java/link/locutus/discord/db/NationDB.java @@ -1,5 +1,7 @@ package link.locutus.discord.db; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.politicsandwar.graphql.model.*; import com.ptsmods.mysqlw.query.builder.SelectBuilder; import com.ptsmods.mysqlw.table.ColumnType; @@ -61,6 +63,7 @@ import link.locutus.discord.apiv1.enums.WarPolicy; import link.locutus.discord.apiv1.enums.city.JavaCity; import link.locutus.discord.util.scheduler.ThrowingTriConsumer; +import org.apache.commons.collections4.map.PassiveExpiringMap; import org.apache.commons.lang3.tuple.Triple; import java.io.IOException; @@ -2888,10 +2891,21 @@ public Map> getRadiationByTurns() { } return result; } + + private final Cache> radiationCache = + CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.MINUTES) + .build(); + public Map getRadiationByTurn(long turn) { + Map cachedResult = radiationCache.getIfPresent(turn); + if (cachedResult != null) { + return cachedResult; + } + Map result = new Object2ObjectOpenHashMap<>(); try (PreparedStatement stmt = getConnection().prepareStatement("SELECT continent, radiation FROM RADIATION_BY_TURN where turn = ?")) { - stmt.setLong(1,turn); + stmt.setLong(1, turn); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { Continent continent = Continent.values[(rs.getInt(1))]; @@ -2899,12 +2913,14 @@ public Map getRadiationByTurn(long turn) { result.put(continent, radiation); } } + radiationCache.put(turn, result); return result; } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException(e); } } + public synchronized void addRadiationByTurn(Continent continent, long turn, double radiation) { try (PreparedStatement stmt = getConnection().prepareStatement("INSERT OR IGNORE INTO RADIATION_BY_TURN (continent, radiation, turn) VALUES (?, ?, ?)")) { stmt.setInt(1, continent.ordinal()); diff --git a/src/main/java/link/locutus/discord/util/sheet/GoogleDoc.java b/src/main/java/link/locutus/discord/util/sheet/GoogleDoc.java index 9778e3e1..66632f20 100644 --- a/src/main/java/link/locutus/discord/util/sheet/GoogleDoc.java +++ b/src/main/java/link/locutus/discord/util/sheet/GoogleDoc.java @@ -151,7 +151,7 @@ private static GoogleDoc create(String id, Docs api, String title) throws Genera return doc; } - private static final PassiveExpiringMap CACHE = new PassiveExpiringMap(5, TimeUnit.MINUTES); + private static final PassiveExpiringMap CACHE = new PassiveExpiringMap<>(5, TimeUnit.MINUTES); private Docs service; private StringBuilder content; diff --git a/src/main/java/link/locutus/discord/util/sheet/SpreadSheet.java b/src/main/java/link/locutus/discord/util/sheet/SpreadSheet.java index 8e2e4901..10b80bfd 100644 --- a/src/main/java/link/locutus/discord/util/sheet/SpreadSheet.java +++ b/src/main/java/link/locutus/discord/util/sheet/SpreadSheet.java @@ -2,12 +2,9 @@ import com.google.api.client.auth.oauth2.TokenResponseException; import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import com.google.api.services.sheets.v4.model.AddSheetRequest; -import com.google.api.services.sheets.v4.model.CellData; -import com.google.api.services.sheets.v4.model.DeleteSheetRequest; -import com.google.api.services.sheets.v4.model.ExtendedValue; -import com.google.api.services.sheets.v4.model.Sheet; -import com.google.api.services.sheets.v4.model.SheetProperties; +import com.google.api.client.http.HttpRequest; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.services.sheets.v4.model.*; import link.locutus.discord.commands.manager.v2.command.IMessageBuilder; import link.locutus.discord.commands.manager.v2.command.IMessageIO; import link.locutus.discord.commands.manager.v2.impl.pw.binding.PWBindings; @@ -30,19 +27,6 @@ import com.google.api.client.util.store.FileDataStoreFactory; import com.google.api.services.sheets.v4.Sheets; import com.google.api.services.sheets.v4.SheetsScopes; -import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetRequest; -import com.google.api.services.sheets.v4.model.BatchUpdateSpreadsheetResponse; -import com.google.api.services.sheets.v4.model.ClearValuesRequest; -import com.google.api.services.sheets.v4.model.ClearValuesResponse; -import com.google.api.services.sheets.v4.model.GridCoordinate; -import com.google.api.services.sheets.v4.model.GridRange; -import com.google.api.services.sheets.v4.model.Request; -import com.google.api.services.sheets.v4.model.RowData; -import com.google.api.services.sheets.v4.model.Spreadsheet; -import com.google.api.services.sheets.v4.model.SpreadsheetProperties; -import com.google.api.services.sheets.v4.model.UpdateCellsRequest; -import com.google.api.services.sheets.v4.model.UpdateValuesResponse; -import com.google.api.services.sheets.v4.model.ValueRange; import com.opencsv.CSVWriter; import link.locutus.discord.apiv1.enums.ResourceType; import org.apache.commons.collections4.map.PassiveExpiringMap; @@ -400,8 +384,19 @@ private SpreadSheet(String id, Sheets api) throws GeneralSecurityException, IOEx private static Sheets getServiceAPI() throws GeneralSecurityException, IOException { final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); - return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) + Credential credentials = getCredentials(HTTP_TRANSPORT); + HttpRequestInitializer requestInitializer = new HttpRequestInitializer() { + @Override + public void initialize(final HttpRequest httpRequest) throws IOException { + credentials.initialize(httpRequest); +// httpRequest.setConnectTimeout(10_000); +// httpRequest.setReadTimeout(10_000); + httpRequest.setNumberOfRetries(3); + } + }; + return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, credentials) .setApplicationName(APPLICATION_NAME) + .setHttpRequestInitializer(requestInitializer) .build(); } @@ -955,6 +950,43 @@ public List> fetchRange(String tab, String range, Consumer>> fetchHeaderRows(Set tabNames) { + Map>> headers = new LinkedHashMap<>(); + if (service == null) { + throw new IllegalStateException("Google Sheets service is not initialized."); + } + + try { + // Prepare the ranges for batch request + List ranges = tabNames.stream() + .map(tab -> tab + "!1:1") + .collect(Collectors.toList()); + + // Create the batch request + Sheets.Spreadsheets.Values.BatchGet request = service.spreadsheets().values().batchGet(spreadsheetId) + .setRanges(ranges); + + // Execute the batch request + BatchGetValuesResponse response = request.execute(); + + // Process the response + List valueRanges = response.getValueRanges(); + for (ValueRange valueRange : valueRanges) { + String range = valueRange.getRange(); + String tabName = range.split("!")[0]; + if (tabName.startsWith("'") && tabName.endsWith("'")) { + tabName = tabName.substring(1, tabName.length() - 1); + } + List> values = valueRange.getValues(); + headers.put(tabName, values != null ? values : Collections.emptyList()); + } + } catch (IOException e) { + throw new RuntimeException("Failed to fetch header rows", e); + } + + return headers; + } + public void updateClearCurrentTab() throws IOException { if (this.defaultTab == null || this.defaultTab.isEmpty()) { updateClearFirstTab();