Search in sources :

Example 1 with SolarThingDatabaseException

use of me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException 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 SolarThingDatabaseException

use of me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException in project solarthing by wildmountainfarms.

the class FlagCommandChatBotHandler method setFlag.

private void setFlag(MessageSender messageSender, String flagName) {
    TimeRange timeRange = TimeRange.createAfter(Instant.now());
    FlagData data = new FlagData(flagName, new TimeRangeActivePeriod(timeRange));
    RequestFlagPacket requestFlagPacket = new ImmutableRequestFlagPacket(data);
    PacketCollectionCreator creator = commandHelper.getCommandManager().makeCreator(sourceId, zoneId, null, requestFlagPacket, PacketCollectionIdGenerator.Defaults.UNIQUE_GENERATOR);
    // TODO We should check if the flag being requested is already active.
    executorService.execute(() -> {
        PacketCollection packetCollection = creator.create(Instant.now());
        boolean success = false;
        try {
            database.getOpenDatabase().uploadPacketCollection(packetCollection, null);
            success = true;
        } catch (SolarThingDatabaseException e) {
            LOGGER.error("Could not upload request flag packet", e);
        }
        if (success) {
            messageSender.sendMessage("Successfully requested flag: '" + flagName + "' to be set.");
        } else {
            messageSender.sendMessage("Was unable to request flag set. See logs for details or try again.");
        }
    });
}
Also used : TimeRange(me.retrodaredevil.solarthing.util.TimeRange) FlagData(me.retrodaredevil.solarthing.type.alter.flag.FlagData) PacketCollection(me.retrodaredevil.solarthing.packets.collection.PacketCollection) TimeRangeActivePeriod(me.retrodaredevil.solarthing.type.alter.flag.TimeRangeActivePeriod) ImmutableRequestFlagPacket(me.retrodaredevil.solarthing.commands.packets.open.ImmutableRequestFlagPacket) RequestFlagPacket(me.retrodaredevil.solarthing.commands.packets.open.RequestFlagPacket) ImmutableRequestFlagPacket(me.retrodaredevil.solarthing.commands.packets.open.ImmutableRequestFlagPacket) PacketCollectionCreator(me.retrodaredevil.solarthing.packets.collection.PacketCollectionCreator) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)

Example 3 with SolarThingDatabaseException

use of me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException in project solarthing by wildmountainfarms.

the class ScheduleCommandChatBotHandler method schedule.

private void schedule(MessageSender messageSender, Instant now, Instant targetTime, AvailableCommand availableCommand) {
    if (now.plus(Duration.ofMinutes(1)).isAfter(targetTime)) {
        messageSender.sendMessage("Cannot schedule a command less than one minute from now.");
        return;
    }
    if (now.plus(Duration.ofHours(72)).isBefore(targetTime)) {
        messageSender.sendMessage("Cannot schedule a command more than 72 hours from now.");
        return;
    }
    UUID uniqueId = UUID.randomUUID();
    PacketCollectionCreator creator = commandHelper.getCommandManager().makeCreator(sourceId, zoneId, // We don't have an InstanceTargetPacket because scheduling commands is not handled by a program with a fragment ID // also look at PacketGroups.parseToTargetPacketGroup() for interpretation without a TargetInstancePacket
    null, new ImmutableScheduleCommandPacket(new ScheduledCommandData(targetTime.toEpochMilli(), availableCommand.getCommandInfo().getName(), Collections.singleton(availableCommand.getFragmentId())), uniqueId), PacketCollectionIdGenerator.Defaults.UNIQUE_GENERATOR);
    PacketCollection packetCollection = creator.create(now);
    messageSender.sendMessage("Scheduling " + availableCommand.getCommandInfo().getDisplayName() + " at " + TimeUtil.instantToSlackDateSeconds(targetTime));
    executorService.execute(() -> {
        boolean success = false;
        try {
            database.getOpenDatabase().uploadPacketCollection(packetCollection, null);
            success = true;
        } catch (SolarThingDatabaseException e) {
            LOGGER.error("Could not upload schedule command packet collection", e);
        }
        if (success) {
            messageSender.sendMessage("Successfully requested schedule. ID: " + uniqueId);
        } else {
            messageSender.sendMessage("Could not upload schedule command request.");
        }
    });
}
Also used : PacketCollection(me.retrodaredevil.solarthing.packets.collection.PacketCollection) UUID(java.util.UUID) PacketCollectionCreator(me.retrodaredevil.solarthing.packets.collection.PacketCollectionCreator) ImmutableScheduleCommandPacket(me.retrodaredevil.solarthing.commands.packets.open.ImmutableScheduleCommandPacket) ScheduledCommandData(me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)

Example 4 with SolarThingDatabaseException

use of me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException in project solarthing by wildmountainfarms.

the class SimpleQueryHandler method queryMeta.

public MetaDatabase queryMeta() {
    final VersionedPacket<RootMetaPacket> metadata;
    synchronized (this) {
        final VersionedPacket<RootMetaPacket> currentCache = metadataCache;
        final Long lastMetadataCacheNanos = this.lastMetadataCacheNanos;
        if (lastMetadataCacheNanos != null && System.nanoTime() - lastMetadataCacheNanos < METADATA_CACHE_VALID.toNanos()) {
            requireNonNull(currentCache);
            metadata = currentCache;
        } else {
            UpdateToken updateToken = currentCache == null ? null : currentCache.getUpdateToken();
            final VersionedPacket<RootMetaPacket> newMetadata;
            try {
                newMetadata = database.queryMetadata(updateToken);
            } catch (NotFoundSolarThingDatabaseException e) {
                // If we have not defined metadata, then we return an "empty" instance
                return EmptyMetaDatabase.getInstance();
            } catch (SolarThingDatabaseException e) {
                throw new DatabaseException("Could not query meta", e);
            }
            this.lastMetadataCacheNanos = System.nanoTime();
            if (newMetadata == null) {
                requireNonNull(currentCache);
                metadata = currentCache;
            } else {
                metadataCache = newMetadata;
                metadata = newMetadata;
            }
        }
    }
    return new DefaultMetaDatabase(metadata.getPacket());
}
Also used : NotFoundSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException) RootMetaPacket(me.retrodaredevil.solarthing.type.closed.meta.RootMetaPacket) DefaultMetaDatabase(me.retrodaredevil.solarthing.type.closed.meta.DefaultMetaDatabase) DatabaseException(me.retrodaredevil.solarthing.rest.exceptions.DatabaseException) NotFoundSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) UpdateToken(me.retrodaredevil.solarthing.database.UpdateToken) NotFoundSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)

Example 5 with SolarThingDatabaseException

use of me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException in project solarthing by wildmountainfarms.

the class SimpleQueryHandler method queryPackets.

/**
 * @param from The date millis from
 * @param to The date millis to
 * @param sourceId The source ID or null. If null, the returned List may contain packet groups from multiple sources
 * @return The resulting packets
 */
private List<? extends InstancePacketGroup> queryPackets(MillisDatabase database, long from, long to, String sourceId) {
    MillisQuery millisQuery = new MillisQueryBuilder().startKey(from).endKey(to).build();
    UniqueQuery uniqueQuery = new UniqueQuery(database, millisQuery);
    final Future<? extends List<? extends PacketGroup>> future;
    {
        // Many times a Grafana dashboard will make many graphql requests with the same from and to parameters.
        // Without this code, each graphql request would result in a separate request to the database.
        // Most of the time, these requests are being executed at the same time.
        // This piece of code takes advantage of the fact that we are requesting the same data at the same time.
        // If we find a Future that is already executing for a given query, we wait for that to complete instead of performing a separate request.
        // This is sort of a caching mechanism, but it's a VERY temporary caching mechanism since data is not kept after is it queried.
        executingQueryMutex.lock();
        var currentFuture = executingQueryMap.get(uniqueQuery);
        if (currentFuture != null) {
            future = currentFuture;
            executingQueryMutex.unlock();
        } else {
            RunnableFuture<? extends List<? extends PacketGroup>> runnableFuture = new FutureTask<>(() -> {
                try {
                    return database.query(millisQuery);
                } catch (SolarThingDatabaseException e) {
                    throw new DatabaseException("Exception querying from " + from + " to " + to, e);
                }
            });
            executingQueryMap.put(uniqueQuery, runnableFuture);
            executingQueryMutex.unlock();
            runnableFuture.run();
            future = runnableFuture;
            executingQueryMutex.lock();
            executingQueryMap.remove(uniqueQuery);
            executingQueryMutex.unlock();
        }
    }
    final List<? extends PacketGroup> rawPacketGroups;
    try {
        rawPacketGroups = future.get();
    } catch (InterruptedException e) {
        throw new DatabaseException("Interrupted!", e);
    } catch (ExecutionException e) {
        Throwable cause = e.getCause();
        if (cause instanceof RuntimeException) {
            throw (RuntimeException) cause;
        }
        throw new DatabaseException("Unknown execution exception", e);
    }
    if (rawPacketGroups.isEmpty()) {
        if (to - from > 60 * 1000) {
            // Only debug this message if the requester is actually asking for a decent chunk of data
            LOGGER.debug("No packets were queried between " + from + " and " + to);
        }
        return Collections.emptyList();
    }
    if (sourceId == null) {
        return PacketGroups.parseToInstancePacketGroups(rawPacketGroups, defaultInstanceOptions);
    }
    Map<String, List<InstancePacketGroup>> map = PacketGroups.parsePackets(rawPacketGroups, defaultInstanceOptions);
    if (map.containsKey(sourceId)) {
        List<InstancePacketGroup> instancePacketGroupList = map.get(sourceId);
        return PacketGroups.orderByFragment(instancePacketGroupList);
    }
    throw new NoSuchElementException("No element with sourceId: '" + sourceId + "' available keys are: " + map.keySet());
}
Also used : MillisQueryBuilder(me.retrodaredevil.solarthing.database.MillisQueryBuilder) NotFoundSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) List(java.util.List) RunnableFuture(java.util.concurrent.RunnableFuture) MillisQuery(me.retrodaredevil.solarthing.database.MillisQuery) ExecutionException(java.util.concurrent.ExecutionException) DatabaseException(me.retrodaredevil.solarthing.rest.exceptions.DatabaseException) NotFoundSolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException) SolarThingDatabaseException(me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

SolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.SolarThingDatabaseException)21 VersionedPacket (me.retrodaredevil.solarthing.database.VersionedPacket)9 Instant (java.time.Instant)7 PacketCollection (me.retrodaredevil.solarthing.packets.collection.PacketCollection)7 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)6 UpdateConflictSolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.UpdateConflictSolarThingDatabaseException)6 PacketCollectionCreator (me.retrodaredevil.solarthing.packets.collection.PacketCollectionCreator)6 MillisQueryBuilder (me.retrodaredevil.solarthing.database.MillisQueryBuilder)5 StoredAlterPacket (me.retrodaredevil.solarthing.type.alter.StoredAlterPacket)5 ArrayList (java.util.ArrayList)4 RequestFlagPacket (me.retrodaredevil.solarthing.commands.packets.open.RequestFlagPacket)4 NotFoundSolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.NotFoundSolarThingDatabaseException)4 FlagData (me.retrodaredevil.solarthing.type.alter.flag.FlagData)4 ScheduledCommandData (me.retrodaredevil.solarthing.type.alter.packets.ScheduledCommandData)4 List (java.util.List)3 JsonData (me.retrodaredevil.couchdbjava.json.JsonData)3 Nullable (me.retrodaredevil.solarthing.annotations.Nullable)3 DeleteAlterPacket (me.retrodaredevil.solarthing.commands.packets.open.DeleteAlterPacket)3 ImmutableRequestCommandPacket (me.retrodaredevil.solarthing.commands.packets.open.ImmutableRequestCommandPacket)3 UnauthorizedSolarThingDatabaseException (me.retrodaredevil.solarthing.database.exception.UnauthorizedSolarThingDatabaseException)3