public synchronized void rescan() { membershipQueue.clear(); Date now = new Date(); for (Player player : Bukkit.getOnlinePlayers()) { for (Membership membership : storageStrategy .getPermissionService() .getGroups(UUIDProvider.retrieve(player.getName()))) { if (membership.getExpiration() != null && membership.getExpiration().after(now)) { membershipQueue.add(membership); } } } debug(plugin, "Potential future expirations: %s", membershipQueue); // Queue up task run(); }
@Override public synchronized void run() { Set<UUID> toRefresh = new LinkedHashSet<>(); final Set<Membership> expired = new LinkedHashSet<>(); // Gather up memberships that have already expired Date now = new Date(); Membership next = membershipQueue.peek(); while (next != null && !next.getExpiration().after(now)) { membershipQueue.remove(); toRefresh.add(next.getUuid()); expired.add(next); now = new Date(); next = membershipQueue.peek(); } debug(plugin, "Refreshing expired players: %s", toRefresh); // NB Metadata cache for offline players not invalidated. // This might become a problem. But nothing can be done unless we // run a timer for each and every membership, online or offline. core.refreshPlayers(toRefresh); // Send notifications if (!expired.isEmpty()) { Bukkit.getScheduler() .scheduleSyncDelayedTask( plugin, new Runnable() { @Override public void run() { for (Membership membership : expired) { Player player = Bukkit.getPlayer(UUIDProvider.retrieve(membership.getUuid())); if (player != null && player.hasPermission("zpermissions.notify.self.expiration")) { sendMessage( player, colorize( "{YELLOW}Your membership to {DARK_GREEN}%s{YELLOW} has expired."), membership.getGroup().getDisplayName()); } broadcast( plugin, "zpermissions.notify.expiration", "Player %s is no longer a member of %s", membership.getDisplayName(), membership.getGroup().getDisplayName()); } } }); } // Cancel previous task if (scheduledFuture != null) { scheduledFuture.cancel(false); scheduledFuture = null; } // Schedule new task if (next != null) { now = new Date(); long delay = next.getExpiration().getTime() - now.getTime(); if (delay < 0L) delay = 0L; // Weird... debug(plugin, "Next expiration is %dms away", delay); final Runnable realThis = this; scheduledFuture = executorService.schedule( new Runnable() { @Override public void run() { debug(plugin, "Expiring..."); Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, realThis); } }, delay + FUDGE, TimeUnit.MILLISECONDS); } else debug(plugin, "No future expirations"); }
@Override public int compare(Membership a, Membership b) { return a.getExpiration().compareTo(b.getExpiration()); }