@Override
    public void removeAffiliation(Node node, NodeAffiliate affiliate) {
        log.debug( "Removing node affiliation for {} (type: {}) on node {}", affiliate.getJID(), affiliate.getAffiliation(), node.getUniqueIdentifier() );
        final List<NodeOperation> operations = nodesToProcess.computeIfAbsent( node.getUniqueIdentifier(), id -> new ArrayList<>() );

        // This affiliation removal can replace any pending creation, update or delete of the same affiliate (since the last create/delete of the node or affiliation change of this affiliate to the node).
        boolean hadCreate = false;
        final ListIterator<NodeOperation> iter = operations.listIterator( operations.size() );
        while ( iter.hasPrevious() ) {
            final NodeOperation operation = iter.previous();
            if ( Arrays.asList( NodeOperation.Action.CREATE_AFFILIATION, NodeOperation.Action.UPDATE_AFFILIATION ).contains( operation.action ) ) {
                if ( affiliate.getJID().equals( operation.affiliate.getJID() ) ) {
                    if (operation.action.equals(NodeOperation.Action.CREATE_AFFILIATION)) {
                        hadCreate = true;
                    }
                    iter.remove(); // This is replaced by the update that's being added.
                }
            } else {
                break; // Operations that precede anything other than the last operations that are affiliate changes shouldn't be replaced.
            }
        }

        if (!hadCreate) { // If one of the operations that have not been executed was an affiliation create, we need not delete the affiliation either.
            operations.add(NodeOperation.removeAffiliation(node, affiliate));
        }
    }
Cache for recently accessed published items.
xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/CachingPubsubPersistenceProvider.java