Skip to content

Inconsistent cache invalidation on /characters/{character_id}/attributes #1483

Description

@snipereagle1

Description

Attribute boosters / skill accelerators expire without invalidating the cache on https://esi.evetech.net/characters/{character_id}/attributes.

Image

Every non-alpha character in this screenshot took a Basic Capsuleer Day booster the night before they expired, the ones that are showing an accelerator off (ghosted zap icon vs. bright yellow) have logged in since then, while the other have not. Once a character is logged into, the attributes endpoint updates to the expected value.

This is particularly frustrating because there is no way from ESI to get the booster state, it has to be derived from the attributes endpoint. Implementation of attribute decomposition looks something like this: https://github.com/snipereagle1/skillmon/blob/98ba128569435b851a6912708b7141764eee61c4/src-tauri/src/refresh/enrichment.rs#L115

TLDR of this code example:

{
    "charisma": 21,
    "intelligence": 25,
    "memory": 35,
    "perception": 29,
    "willpower": 25
}
  • subtract base values (static, 17 per attribute)
{
    "charisma": 4,
    "intelligence": 8,
    "memory": 18,
    "perception": 12,
    "willpower": 8
}
{
    "charisma": 4,
    "intelligence": 4,
    "memory": 14,
    "perception": 8,
    "willpower": 4
}
  • subtract the remap points (total 14, distributed per the linked code) so only the uniform component remains
{
    "charisma": 4,
    "intelligence": 4,
    "memory": 4,
    "perception": 4,
    "willpower": 4
}
  • whatever remains is the booster: 0 means no accelerator, +X means a +X accelerator applied to every attribute (here +4)

Which lets me create a UI like this:

Image

Ideally on booster expiration, the following endpoints would have their cache invalidated:

Stretch goal would be adding something like the request in #783 so that I don't have to derive whether a booster is active, or updating https://esi.evetech.net/characters/{character_id}/attributes with a breakdown object something like this (any format of decomposed breakdown would be useful, this is just what I came up with):

{
    "accrued_remap_cooldown_date": "2027-04-09T05:27:53Z",
    "bonus_remaps": 2,
    "charisma": 21,
    "intelligence": 25,
    "last_remap_date": "2026-04-09T05:27:53Z",
    "memory": 35,
    "perception": 29,
    "willpower": 25,
    "breakdown": {
        "charisma": {
          "base": 17,
          "implant": 0,
          "remap": 0,
          "accelerator": 4
        },
        "intelligence": {
          "base": 17,
          "implant": 4,
          "remap": 0,
          "accelerator": 4
        },
        "memory": {
          "base": 17,
          "implant": 4,
          "remap": 10,
          "accelerator": 4
        },
        "perception": {
          "base": 17,
          "implant": 4,
          "remap": 4,
          "accelerator": 4
        },
        "willpower": {
          "base": 17,
          "implant": 4,
          "remap": 0,
          "accelerator": 4
        }
    }
}

Request

GET /characters/2114260517/attributes

Compatibility Date

2026-06-09

Response - Status Code

304

Response - Headers

access-control-allow-origin
*
access-control-expose-headers
Etag, Retry-After, X-Compatibility-Date, X-Esi-Error-Limit-Remain, X-Esi-Error-Limit-Reset, X-Pages, X-Ratelimit-Group, X-Ratelimit-Limit, X-Ratelimit-Remaining, X-Ratelimit-Used

cache-control
private
content-language
en
date
Fri, 12 Jun 2026 17:45:02 GMT
etag
"1a84093e781e6eae4fc7217e165f486bb73ab5d30ae8f5d37530c0ec"
expires
Fri, 12 Jun 2026 17:46:23 GMT
last-modified
Fri, 12 Jun 2026 17:44:23 GMT
strict-transport-security
max-age=31536000
vary
Accept-Language
vary
X-Compatibility-Date
x-compatibility-date
2020-01-01
x-esi-cache-status
HIT
x-esi-request-id
08d1b7a7-7fe4-48ac-a5ee-d025644976a8
x-ratelimit-group
char-detail
x-ratelimit-limit
600/15m
x-ratelimit-remaining
598
x-ratelimit-used
1

Response - Body

{
    "accrued_remap_cooldown_date": "2027-04-09T05:27:53Z",
    "bonus_remaps": 2,
    "charisma": 21,
    "intelligence": 25,
    "last_remap_date": "2026-04-09T05:27:53Z",
    "memory": 35,
    "perception": 29,
    "willpower": 25
}

Expected Response

{
    "accrued_remap_cooldown_date": "2027-04-09T05:27:53Z",
    "bonus_remaps": 2,
    "charisma": 17,
    "intelligence": 21,
    "last_remap_date": "2026-04-09T05:27:53Z",
    "memory": 31,
    "perception": 25,
    "willpower": 21
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions