diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/async/AsyncJobCallback.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/async/AsyncJobCallback.java index 4aeefb90..77217531 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/async/AsyncJobCallback.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/async/AsyncJobCallback.java @@ -97,6 +97,30 @@ public class AsyncJobCallback + /******************************************************************************* + ** Increase the 'current' value in the '1 of 2' sense. + *******************************************************************************/ + public void incrementCurrent() + { + incrementCurrent(1); + } + + + + /******************************************************************************* + ** Increase the 'current' value in the '1 of 2' sense. + *******************************************************************************/ + public void incrementCurrent(int amount) + { + if(this.asyncJobStatus.getCurrent() != null) + { + this.asyncJobStatus.setCurrent(this.asyncJobStatus.getCurrent() + amount); + storeUpdatedStatus(); + } + } + + + /******************************************************************************* ** Remove the values from the current & total fields *******************************************************************************/ diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java index 9a4b2415..e776ded0 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/automation/polling/PollingAutomationPerTableRunner.java @@ -174,7 +174,7 @@ public class PollingAutomationPerTableRunner implements Runnable public void run() { Thread.currentThread().setName(name); - LOG.info("Running " + this.getClass().getSimpleName() + "[" + name + "]"); + LOG.debug("Running " + this.getClass().getSimpleName() + "[" + name + "]"); try { diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaDeleteStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaDeleteStep.java index 34aa0d3b..9697f1c4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaDeleteStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaDeleteStep.java @@ -58,6 +58,7 @@ public class LoadViaDeleteStep extends AbstractLoadStep deleteInput.setSession(runBackendStepInput.getSession()); deleteInput.setTableName(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE)); deleteInput.setPrimaryKeys(runBackendStepInput.getRecords().stream().map(r -> r.getValue(table.getPrimaryKeyField())).collect(Collectors.toList())); + deleteInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback()); // todo? can make more efficient deletes, maybe? deleteInput.setQueryFilter(); getTransaction().ifPresent(deleteInput::setTransaction); new DeleteAction().execute(deleteInput); diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertOrUpdateStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertOrUpdateStep.java index b75c9edb..3254e71e 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertOrUpdateStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertOrUpdateStep.java @@ -82,6 +82,7 @@ public class LoadViaInsertOrUpdateStep extends AbstractLoadStep insertInput.setTableName(tableMetaData.getName()); insertInput.setRecords(runBackendStepInput.getRecords()); getTransaction().ifPresent(insertInput::setTransaction); + insertInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback()); InsertOutput insertOutput = new InsertAction().execute(insertInput); runBackendStepOutput.getRecords().addAll(insertOutput.getRecords()); } @@ -93,6 +94,7 @@ public class LoadViaInsertOrUpdateStep extends AbstractLoadStep updateInput.setTableName(tableMetaData.getName()); updateInput.setRecords(runBackendStepInput.getRecords()); getTransaction().ifPresent(updateInput::setTransaction); + updateInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback()); UpdateOutput updateOutput = new UpdateAction().execute(updateInput); runBackendStepOutput.getRecords().addAll(updateOutput.getRecords()); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertStep.java index 4903a710..8e6a7979 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaInsertStep.java @@ -54,6 +54,7 @@ public class LoadViaInsertStep extends AbstractLoadStep insertInput.setTableName(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE)); insertInput.setRecords(runBackendStepInput.getRecords()); getTransaction().ifPresent(insertInput::setTransaction); + insertInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback()); InsertOutput insertOutput = new InsertAction().execute(insertInput); runBackendStepOutput.getRecords().addAll(insertOutput.getRecords()); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaUpdateStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaUpdateStep.java index 39572ee1..b8f6abe8 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaUpdateStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/streamedwithfrontend/LoadViaUpdateStep.java @@ -56,6 +56,7 @@ public class LoadViaUpdateStep extends AbstractLoadStep updateInput.setTableName(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE)); updateInput.setRecords(runBackendStepInput.getRecords()); getTransaction().ifPresent(updateInput::setTransaction); + updateInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback()); UpdateOutput updateOutput = new UpdateAction().execute(updateInput); runBackendStepOutput.getRecords().addAll(updateOutput.getRecords()); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/scheduler/StandardScheduledExecutor.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/scheduler/StandardScheduledExecutor.java index 7ae7d4dd..f4955661 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/scheduler/StandardScheduledExecutor.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/scheduler/StandardScheduledExecutor.java @@ -89,7 +89,7 @@ public class StandardScheduledExecutor { if(!runningState.equals(RunningState.STOPPED)) { - LOG.info("Request to start from an invalid running state [" + runningState + "]. Must be STOPPED."); + LOG.warn("Request to start from an invalid running state [" + runningState + "]. Must be STOPPED."); return (false); } @@ -121,7 +121,7 @@ public class StandardScheduledExecutor { if(!runningState.equals(RunningState.RUNNING)) { - LOG.info("Request to stop from an invalid running state [" + runningState + "]. Must be RUNNING."); + LOG.warn("Request to stop from an invalid running state [" + runningState + "]. Must be RUNNING."); return (false); } @@ -138,7 +138,7 @@ public class StandardScheduledExecutor return (true); } - LOG.info("Timed out waiting for service to fully terminate. Will be left in STOPPING state."); + LOG.warn("Timed out waiting for service to fully terminate. Will be left in STOPPING state."); } catch(InterruptedException ie) { diff --git a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIInsertAction.java b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIInsertAction.java index 64a75e02..75a952b2 100644 --- a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIInsertAction.java +++ b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/APIInsertAction.java @@ -81,6 +81,12 @@ public class APIInsertAction extends AbstractAPIAction implements InsertInterfac for(QRecord record : insertInput.getRecords()) { + ////////////////////////////////////////////////////////// + // hmm, unclear if this should always be done... // + // is added initially for registering easypost trackers // + ////////////////////////////////////////////////////////// + insertInput.getAsyncJobCallback().incrementCurrent(); + postOneRecord(insertOutput, table, connectionManager, record); if(insertInput.getRecords().size() > 1 && apiActionUtil.getMillisToSleepAfterEveryCall() > 0) diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostApiTest.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostApiTest.java index 16d98fc9..81e4427a 100644 --- a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostApiTest.java +++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostApiTest.java @@ -32,8 +32,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -42,7 +43,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; /******************************************************************************* ** *******************************************************************************/ -@Disabled // OnOs(OS.LINUX) +@DisabledOnOs(OS.LINUX) public class EasyPostApiTest { diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostUtils.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostUtils.java index f8309bc9..b81d03f8 100644 --- a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostUtils.java +++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/EasyPostUtils.java @@ -5,9 +5,12 @@ package com.kingsrook.qqq.backend.module.api; +import java.io.IOException; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.module.api.actions.BaseAPIActionUtil; +import org.apache.http.entity.AbstractHttpEntity; +import org.apache.http.entity.StringEntity; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.json.JSONObject; @@ -23,14 +26,21 @@ public class EasyPostUtils extends BaseAPIActionUtil /******************************************************************************* + ** Build an HTTP Entity (e.g., for a PUT or POST) from a QRecord. Can be + ** overridden if an API doesn't do a basic json object. Or, can override a + ** helper method, such as recordToJsonObject. ** *******************************************************************************/ @Override - protected JSONObject recordToJsonObject(QTableMetaData table, QRecord record) + protected AbstractHttpEntity recordToEntity(QTableMetaData table, QRecord record) throws IOException { - JSONObject inner = super.recordToJsonObject(table, record); - JSONObject outer = new JSONObject(); - outer.put(getBackendDetails(table).getTableWrapperObjectName(), inner); - return (outer); + JSONObject body = recordToJsonObject(table, record); + JSONObject wrapper = new JSONObject(); + String tablePath = getBackendDetails(table).getTableWrapperObjectName(); + wrapper.put(tablePath, body); + String json = wrapper.toString(); + LOG.debug(json); + return (new StringEntity(json)); } + } diff --git a/qqq-dev-tools/bin/end-of-sprint-release.sh b/qqq-dev-tools/bin/end-of-sprint-release.sh index 851a4d2d..14a2eecb 100755 --- a/qqq-dev-tools/bin/end-of-sprint-release.sh +++ b/qqq-dev-tools/bin/end-of-sprint-release.sh @@ -36,8 +36,8 @@ gumBanner "Getting dev & main branches up to date and ready" git checkout main && git pull && git checkout dev && git pull if [ ! -e "qqq-sample-project/.env" ]; then - dir=$(realpath qqq-sample-project) - gumBanner "Installing .env file -- for qqq-sample-project" "Tell it your qqq is at:" "$dir" + dir=$(realpath .) + gumBanner "Installing .env file -- for qqq" "Tell it your qqq is at:" "$dir" setup-environments.sh --qqq --quiet fi diff --git a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java index 9af73f36..4c29884f 100644 --- a/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java +++ b/qqq-middleware-javalin/src/main/java/com/kingsrook/qqq/backend/javalin/QJavalinImplementation.java @@ -379,6 +379,8 @@ public class QJavalinImplementation { context.cookie(SESSION_ID_COOKIE_NAME, session.getIdReference(), SESSION_COOKIE_AGE); } + + setUserTimezoneOffsetMinutesHeaderInSession(context, session); } catch(QAuthenticationException qae) { @@ -394,6 +396,30 @@ public class QJavalinImplementation + /******************************************************************************* + ** + *******************************************************************************/ + private static void setUserTimezoneOffsetMinutesHeaderInSession(Context context, QSession session) + { + String userTimezoneOffsetMinutes = context.header("X-QQQ-UserTimezoneOffsetMinutes"); + if(StringUtils.hasContent(userTimezoneOffsetMinutes)) + { + try + { + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // even though we're putting it in the session as a string, go through parse int, to make sure it's a valid int. // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + session.setValue("UserTimezoneOffsetMinutes", String.valueOf(Integer.parseInt(userTimezoneOffsetMinutes))); + } + catch(Exception e) + { + LOG.debug("Received non-integer value for X-QQQ-UserTimezoneOffsetMinutes header: " + userTimezoneOffsetMinutes); + } + } + } + + + /******************************************************************************* ** *******************************************************************************/