Search in sources :

Example 1 with VersionedPacket

use of me.retrodaredevil.solarthing.database.VersionedPacket in project solarthing by wildmountainfarms.

the class AlterManagerAction method onUpdate.

@Override
protected void onUpdate() {
    super.onUpdate();
    // Supply queried solarthing_open packets to the security packet receiver, which may execute code to put commands requested to be scheduled in solarthing_alter
    List<StoredPacketGroup> packets = openDatabaseCache.getAllCachedPackets();
    securityPacketReceiver.receivePacketGroups(packets);
    // Check packets in solarthing_alter and see if we need to send a command because of a scheduled command packet
    Instant now = Instant.now();
    List<VersionedPacket<StoredAlterPacket>> alterPackets = alterPacketsProvider.getPackets();
    if (alterPackets == null) {
        LOGGER.info("alterPackets is null. Maybe query failed? Maybe additional info in previous logs?");
    } else {
        for (VersionedPacket<StoredAlterPacket> versionedPacket : alterPackets) {
            AlterPacket packet = versionedPacket.getPacket().getPacket();
            if (packet instanceof ScheduledCommandPacket) {
                ScheduledCommandPacket scheduledCommandPacket = (ScheduledCommandPacket) packet;
                ScheduledCommandData data = scheduledCommandPacket.getData();
                if (data.getScheduledTimeMillis() <= now.toEpochMilli()) {
                    if (now.toEpochMilli() - data.getScheduledTimeMillis() > Duration.ofMinutes(5).toMillis()) {
                        LOGGER.warn("Not going to send a command scheduled for more than 5 minutes ago! data: " + data);
                    } else {
                        doSendCommand(versionedPacket, scheduledCommandPacket);
                    }
                }
            } else if (packet instanceof FlagPacket) {
                FlagPacket flagPacket = (FlagPacket) packet;
                FlagData data = flagPacket.getFlagData();
                ActivePeriod activePeriod = data.getActivePeriod();
                if (activePeriod instanceof TimeRangeActivePeriod) {
                    // We only try to "manage" flags that use this type of ActivePeriod
                    TimeRangeActivePeriod period = (TimeRangeActivePeriod) activePeriod;
                    TimeRange timeRange = period.getTimeRange();
                    Instant endTime = timeRange.getEndTime();
                    if (endTime != null && endTime.compareTo(now) < 0) {
                        // If there is an end time, and it is in the past, then we should remove the flag
                        executorService.execute(() -> {
                            try {
                                database.getAlterDatabase().delete(versionedPacket);
                            } catch (SolarThingDatabaseException e) {
                                LOGGER.error("Could not delete a FlagPacket with an expired time", e);
                            // If we cannot delete it, no need to try again, it'll still be here next time around
                            }
                        });
                    }
                }
            }
        }
    }
}
Also used : FlagPacket(me.retrodaredevil.solarthing.type.alter.packets.FlagPacket) RequestFlagPacket(me.retrodaredevil.solarthing.commands.packets.open.RequestFlagPacket) ImmutableStoredAlterPacket(me.retrodaredevil.solarthing.type.alter.ImmutableStoredAlterPacket) StoredAlterPacket(me.retrodaredevil.solarthing.type.alter.StoredAlterPacket) Instant(java.time.Instant) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) ActivePeriod(me.retrodaredevil.solarthing.type.alter.flag.ActivePeriod) TimeRangeActivePeriod(me.retrodaredevil.solarthing.type.alter.flag.TimeRangeActivePeriod) ImmutableStoredAlterPacket(me.retrodaredevil.solarthing.type.alter.ImmutableStoredAlterPacket) DeleteAlterPacket(me.retrodaredevil.solarthing.commands.packets.open.DeleteAlterPacket) StoredAlterPacket(me.retrodaredevil.solarthing.type.alter.StoredAlterPacket) AlterPacket(me.retrodaredevil.solarthing.type.alter.AlterPacket) TimeRangeActivePeriod(me.retrodaredevil.solarthing.type.alter.flag.TimeRangeActivePeriod) UpdateConflictSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.UpdateConflictSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) TimeRange(me.retrodaredevil.solarthing.util.TimeRange) ScheduledCommandPacket(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandPacket) FlagData(me.retrodaredevil.solarthing.type.alter.flag.FlagData) StoredPacketGroup(me.retrodaredevil.solarthing.packets.collection.StoredPacketGroup) ScheduledCommandData(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData)

Example 2 with VersionedPacket

use of me.retrodaredevil.solarthing.database.VersionedPacket in project solarthing by wildmountainfarms.

the class FlagActionNode method createAction.

@Override
public Action createAction(ActionEnvironment actionEnvironment) {
    AlterPacketsEnvironment alterPacketsEnvironment = actionEnvironment.getInjectEnvironment().get(AlterPacketsEnvironment.class);
    AlterPacketsProvider provider = alterPacketsEnvironment.getAlterPacketsProvider();
    return new SimpleAction(false) {

        @Override
        protected void onUpdate() {
            super.onUpdate();
            List<VersionedPacket<StoredAlterPacket>> packets = provider.getPackets();
            if (packets != null) {
                Instant now = Instant.now();
                if (FlagUtil.isFlagActive(now, flagName, packets.stream().map(VersionedPacket::getPacket)) != not) {
                    setDone(true);
                }
            }
        }
    };
}
Also used : AlterPacketsProvider(me.retrodaredevil.solarthing.AlterPacketsProvider) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) Instant(java.time.Instant) AlterPacketsEnvironment(me.retrodaredevil.solarthing.actions.environment.AlterPacketsEnvironment) SimpleAction(me.retrodaredevil.action.SimpleAction)

Example 3 with VersionedPacket

use of me.retrodaredevil.solarthing.database.VersionedPacket in project solarthing by wildmountainfarms.

the class AlterManagerAction method doSendCommand.

private void doSendCommand(VersionedPacket<StoredAlterPacket> versionedPacket, ScheduledCommandPacket scheduledCommandPacket) {
    LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Sending command from data: " + scheduledCommandPacket.getData());
    ScheduledCommandData data = scheduledCommandPacket.getData();
    RequestCommandPacket requestCommandPacket = new ImmutableRequestCommandPacket(data.getCommandName());
    // Having a document ID based off of the StoredAlterPacket's _id helps make sure we don't process it twice in case we are unable to delete it.
    // -- if there's an update conflict while uploading, we know we already processed it
    String documentId = "scheduled-request-" + versionedPacket.getPacket().getDbId();
    PacketCollectionCreator creator = commandManager.makeCreator(sourceId, zoneId, InstanceTargetPackets.create(data.getTargetFragmentIds()), requestCommandPacket, zonedDateTime -> documentId);
    executorService.execute(() -> {
        Instant uploadingNow = Instant.now();
        PacketCollection packetCollection = creator.create(uploadingNow);
        boolean shouldDeleteAlter = false;
        try {
            database.getOpenDatabase().uploadPacketCollection(packetCollection, null);
            LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Successfully uploaded packet collection that schedules command from data: " + scheduledCommandPacket.getData() + " document ID: " + documentId);
            shouldDeleteAlter = true;
        } catch (UpdateConflictSolarThingDatabaseException e) {
            LOGGER.error("Got update conflict exception while uploading document ID: " + documentId + ". Will inspect existing document and overwrite if it's a malicious actor...", e);
            VersionedPacket<StoredPacketGroup> existingDocument = null;
            try {
                existingDocument = database.getOpenDatabase().getPacketCollection(documentId);
            } catch (SolarThingDatabaseException ex) {
                LOGGER.error("Could not retrieve document with document ID: " + documentId, ex);
            }
            if (existingDocument != null) {
                if (isDocumentMadeByUs(uploadingNow, data, existingDocument.getPacket())) {
                    LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "False alarm everyone. The packet in the database was made by us and its timestamp is reasonable. document ID: " + documentId);
                    shouldDeleteAlter = true;
                } else {
                    LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "The packet in the database with document ID: " + documentId + " was not made by us. Could be a malicious actor. We will overwrite that packet.");
                    try {
                        database.getOpenDatabase().uploadPacketCollection(packetCollection, existingDocument.getUpdateToken());
                        shouldDeleteAlter = true;
                    } catch (SolarThingDatabaseException ex) {
                        LOGGER.error("Could not overwrite malicious packet. Will likely try again. document ID: " + documentId, ex);
                    }
                }
            }
        } catch (SolarThingDatabaseException e) {
            LOGGER.error("Failed to upload our request command packet. documentId: " + documentId, e);
        }
        if (shouldDeleteAlter) {
            try {
                database.getAlterDatabase().delete(versionedPacket);
            } catch (SolarThingDatabaseException e) {
                LOGGER.error("Error while deleting an alter document. document ID: " + versionedPacket.getPacket().getDbId() + " update token: " + versionedPacket.getUpdateToken(), e);
            }
        }
    });
}
Also used : RequestCommandPacket(me.retrodaredevil.solarthing.commands.packets.open.RequestCommandPacket) ImmutableRequestCommandPacket(me.retrodaredevil.solarthing.commands.packets.open.ImmutableRequestCommandPacket) PacketCollection(me.retrodaredevil.solarthing.packets.collection.PacketCollection) Instant(java.time.Instant) UpdateConflictSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.UpdateConflictSolarThingDatabaseException) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) ImmutableRequestCommandPacket(me.retrodaredevil.solarthing.commands.packets.open.ImmutableRequestCommandPacket) ScheduledCommandData(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData) PacketCollectionCreator(me.retrodaredevil.solarthing.packets.collection.PacketCollectionCreator) UpdateConflictSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.UpdateConflictSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)

Example 4 with VersionedPacket

use of me.retrodaredevil.solarthing.database.VersionedPacket in project solarthing by wildmountainfarms.

the class CouchDbMillisDatabase method jsonDataToStoredPacketGroup.

private VersionedPacket<StoredPacketGroup> jsonDataToStoredPacketGroup(JsonData jsonData) throws SolarThingDatabaseException {
    final JsonNode jsonNode;
    try {
        jsonNode = CouchDbJacksonUtil.getNodeFrom(jsonData);
    } catch (JsonProcessingException e) {
        throw new SolarThingDatabaseException("We couldn't parse some of the data into JSON. This should never happen", e);
    }
    if (!jsonNode.isObject()) {
        throw new SolarThingDatabaseException("Something must be wrong with the packet millis view because we got this jsonNode: " + jsonNode);
    }
    ObjectNode objectNode = (ObjectNode) jsonNode;
    final PacketGroup packetGroup;
    try {
        packetGroup = parser.parse(objectNode);
    } catch (PacketParseException e) {
        throw new SolarThingDatabaseException(e);
    }
    String documentId = objectNode.get("_id").asText();
    String documentRevision = objectNode.get("_rev").asText();
    StoredPacketGroup storedPacketGroup = PacketGroups.createStoredPacketGroup(packetGroup, new CouchDbStoredIdentifier(packetGroup.getDateMillis(), documentId, documentRevision));
    return new VersionedPacket<>(storedPacketGroup, new RevisionUpdateToken(documentRevision));
}
Also used : PacketGroup(me.retrodaredevil.solarthing.packets.collection.PacketGroup) StoredPacketGroup(me.retrodaredevil.solarthing.packets.collection.StoredPacketGroup) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) PacketParseException(me.retrodaredevil.solarthing.packets.collection.parsing.PacketParseException) JsonNode(com.fasterxml.jackson.databind.JsonNode) StoredPacketGroup(me.retrodaredevil.solarthing.packets.collection.StoredPacketGroup) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)

Example 5 with VersionedPacket

use of me.retrodaredevil.solarthing.database.VersionedPacket in project solarthing by wildmountainfarms.

the class CouchDbSolarThingDatabase method queryMetadata.

@Override
@Nullable
public VersionedPacket<RootMetaPacket> queryMetadata(UpdateToken updateToken) throws SolarThingDatabaseException {
    DocumentData data = queryDocument(closedDatabase, RootMetaPacket.DOCUMENT_ID, updateToken);
    if (data == null) {
        return null;
    }
    JsonData jsonData = data.getJsonData();
    try {
        RootMetaPacket packet = CouchDbJacksonUtil.readValue(metaObjectMapper, jsonData, RootMetaPacket.class);
        return new VersionedPacket<>(packet, new RevisionUpdateToken(data.getRevision()));
    } catch (JsonProcessingException e) {
        throw new SolarThingDatabaseException("Invalid meta! Failed to parse!", e);
    }
}
Also used : DocumentData(me.retrodaredevil.couchdbjava.response.DocumentData) VersionedPacket(me.retrodaredevil.solarthing.database.VersionedPacket) RootMetaPacket(me.retrodaredevil.solarthing.type.closed.meta.RootMetaPacket) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) JsonData(me.retrodaredevil.couchdbjava.json.JsonData) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) Nullable(me.retrodaredevil.solarthing.annotations.Nullable)

Aggregations

VersionedPacket (me.retrodaredevil.solarthing.database.VersionedPacket)10 SolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)8 Instant (java.time.Instant)5 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)4 StoredAlterPacket (me.retrodaredevil.solarthing.type.alter.StoredAlterPacket)4 JsonData (me.retrodaredevil.couchdbjava.json.JsonData)3 Nullable (me.retrodaredevil.solarthing.annotations.Nullable)3 UpdateConflictSolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.UpdateConflictSolarThingDatabaseException)3 PacketCollection (me.retrodaredevil.solarthing.packets.collection.PacketCollection)3 PacketCollectionCreator (me.retrodaredevil.solarthing.packets.collection.PacketCollectionCreator)3 AlterPacket (me.retrodaredevil.solarthing.type.alter.AlterPacket)3 ScheduledCommandData (me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData)3 JsonNode (com.fasterxml.jackson.databind.JsonNode)2 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 DocumentData (me.retrodaredevil.couchdbjava.response.DocumentData)2 AlterPacketsProvider (me.retrodaredevil.solarthing.AlterPacketsProvider)2 NotNull (me.retrodaredevil.solarthing.annotations.NotNull)2 DeleteAlterPacket (me.retrodaredevil.solarthing.commands.packets.open.DeleteAlterPacket)2