package im.actor.core.modules.sequence; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import im.actor.core.api.ApiGroup; import im.actor.core.api.ApiGroupOutPeer; import im.actor.core.api.ApiUser; import im.actor.core.api.ApiUserOutPeer; import im.actor.core.api.rpc.RequestGetReferencedEntitites; import im.actor.core.modules.ModuleContext; import im.actor.core.modules.sequence.internal.HandlerDifferenceUpdates; import im.actor.core.modules.sequence.internal.HandlerSeqUpdate; import im.actor.core.modules.sequence.internal.HandlerWeakUpdate; import im.actor.core.modules.sequence.internal.HandlerRelatedResponse; import im.actor.core.modules.ModuleActor; import im.actor.core.modules.sequence.processor.UpdateProcessor; import im.actor.core.network.parser.Update; import im.actor.runtime.Log; import im.actor.runtime.Runtime; import im.actor.runtime.actors.ActorCreator; import im.actor.runtime.actors.messages.Void; import im.actor.runtime.function.Constructor; import im.actor.runtime.function.Function; import im.actor.runtime.promise.Promise; import im.actor.runtime.promise.PromiseFunc; import im.actor.runtime.promise.Promises; import im.actor.runtime.promise.PromisesArray; /*-[ #pragma clang diagnostic ignored "-Wnullability-completeness" ]-*/ public class SequenceHandlerActor extends ModuleActor { public static ActorCreator CONSTRUCTOR(final ModuleContext context) { return () -> new SequenceHandlerActor(context); } private static final String TAG = "SequenceHandlerActor"; // Do Not Remove! WorkAround for missing j2objc translator include private static final Void DUMB = null; private final UpdateProcessor processor; private boolean isUpdating; public SequenceHandlerActor(ModuleContext context) { super(context); this.processor = new UpdateProcessor(context); } // // Sequenced data // private Promise<Void> onSeqUpdate(final Update update, @Nullable List<ApiUser> users, @Nullable List<ApiGroup> groups) throws Exception { Log.d(TAG, "Processing update: " + update); beginUpdates(); // Related Users Promise<Void> currentPromise; if (groups != null && users != null && (users.size() > 0 || groups.size() > 0)) { currentPromise = updates().applyRelatedData(users, groups); } else { currentPromise = Promise.success(null); } // Update Application currentPromise = currentPromise .chain(v -> processor.processUpdate(update)) .then(v -> { Log.d(TAG, "Ended processing update: " + update); }); // Handling update end currentPromise.then(v -> endUpdates()); // TODO: Wait database flush return currentPromise; } private Promise<Void> onDifferenceUpdate(@NotNull List<ApiUser> users, @NotNull List<ApiGroup> groups, @NotNull List<ApiUserOutPeer> userOutPeers, @NotNull List<ApiGroupOutPeer> groupOutPeers, @NotNull List<Update> updates) { if (updates.size() > 0) { String command = "Difference updates:"; for (Update u : updates) { command += "\n| " + u; } Log.d(TAG, command); } beginUpdates(); // Related Users Promise<Void> currentPromise = updates().applyRelatedData(users, groups); // Loading missing peers currentPromise = currentPromise.chain(v -> updates().loadRequiredPeers(userOutPeers, groupOutPeers)); // Apply Diff long applyStart = im.actor.runtime.Runtime.getCurrentTime(); currentPromise = currentPromise .chain(v -> processor.applyDifferenceUpdate(updates)) .then(v -> { Log.d(TAG, "Difference applied in " + (im.actor.runtime.Runtime.getCurrentTime() - applyStart) + " ms"); endUpdates(); }); // TODO: Wait database flush return currentPromise; } // // Weak Updates // private void onWeakUpdateReceived(Update update, long date) { Log.d(TAG, "Processing weak update: " + update); this.processor.processWeakUpdate(update, date); } // // Tools // private void beginUpdates() { isUpdating = true; } private void endUpdates() { isUpdating = false; unstashAll(); } // // Message Processing // @Override public void onReceive(Object message) { if (message instanceof HandlerWeakUpdate) { HandlerWeakUpdate weakUpdate = (HandlerWeakUpdate) message; try { onWeakUpdateReceived(weakUpdate.getUpdate(), weakUpdate.getDate()); } catch (Exception e) { e.printStackTrace(); } } else { super.onReceive(message); } } @Override public Promise onAsk(Object message) throws Exception { if (message instanceof HandlerSeqUpdate) { HandlerSeqUpdate seqUpdate = (HandlerSeqUpdate) message; if (isUpdating) { stash(); return null; } return onSeqUpdate(seqUpdate.getUpdate(), seqUpdate.getUsers(), seqUpdate.getGroups()); } else if (message instanceof HandlerDifferenceUpdates) { HandlerDifferenceUpdates differenceUpdate = (HandlerDifferenceUpdates) message; if (isUpdating) { stash(); return null; } return onDifferenceUpdate( differenceUpdate.getUsers(), differenceUpdate.getGroups(), differenceUpdate.getUserOutPeers(), differenceUpdate.getGroupOutPeers(), differenceUpdate.getUpdates()); } else { return super.onAsk(message); } } }