Expiration
Listings expire after listing-expiry-days from timestamp; timer every 30 minutes plus plugin start.
Based on GrzybcioRynek 1.0.3 and web 0.1.0 source.
Listing lifetime = settings.listing-expiry-days days from MarketListing.timestamp. Default 7. Check: on onEnable and every 30 minutes (20L * 60 * 30 ticks) in MarketPlace. Also after /market reload.
Condition
now - timestamp > listing-expiry-days in milliseconds
A reserved listing (purchase in progress) is not expired in that run.
Flow (StorageManager.removeExpiredListings)
- Collect expired, skipping
reservedListings. - First write journal
expiry-outbox.<id>(seller, item, price, reasonexpired) and clear favorites. - Remove listings from the list,
save(). processExpiryOutbox()— deliver item.
Journal → remove order exists so a crash cannot lose the item or duplicate the listing.
Outbox
expiry-outbox:
"42":
seller: "069a79f4-44e9-4726-a5be-fca90e38aaf5"
item: {==: org.bukkit.inventory.ItemStack, type: DIAMOND, amount: 16}
price: 100.0
reason: expiredOn processing the entry is deleted before delivery; on delivery error the item returns to outbox / mailbox.
Where the item goes
| Situation | Result |
|---|---|
| Seller online, has space | Inventory + messages.expiry.returned |
| Online, no space / remainder | Mailbox (mailbox.enabled) or drop / pending-returns |
| Offline, mailbox enabled | market-data.yml mailbox, reason expired |
| Offline, mailbox disabled | listings.yml → pending-returns.<uuid> |
/market admin forceexpire <id> uses the same return path with reason expired (without waiting for the timer).
Configuration
settings:
listing-expiry-days: 70 means immediate expiry on the next timer tick (time difference > 0). Do not set negative values — the code does not sanitize them separately.
Full key description: configuration/expiration.