'Sends the add and remove commands to the storage layer based on a diff
of
:param new: list of new items
:param changed: list of tuples (from, to)
:param deleted: list of things to delete'

def _update_from_diff(self, new, changed, deleted):

    msg_format = 'now    updating    from    diff    new:    %s    changed:    %s    deleted:    %s'
    logger.debug(msg_format, *map(len, [new, changed, deleted]))
    (to_remove, to_add) = self._translate_diff(new, changed, deleted)
    with self.get_timeline_batch_interface() as batch_interface:
        if to_remove:
            self.remove_many_aggregated(to_remove, batch_interface=batch_interface)
    with self.get_timeline_batch_interface() as batch_interface:
        if to_add:
            self.add_many_aggregated(to_add, batch_interface=batch_interface)
    logger.debug('removed    %s,    added    %s    items    from    feed    %s', len(to_remove), len(to_add), self)
    new_aggregated = new[:]
    if changed:
        new_aggregated += list(zip(*changed))[1]
    self.on_update_feed(to_add, to_remove)
    return new_aggregated
