{"action":"closed","issue":{"url":"https://api.github.com/repos/18F/api.data.gov/issues/187","labels_url":"https://api.github.com/repos/18F/api.data.gov/issues/187/labels{/name}","comments_url":"https://api.github.com/repos/18F/api.data.gov/issues/187/comments","events_url":"https://api.github.com/repos/18F/api.data.gov/issues/187/events","html_url":"https://github.com/18F/api.data.gov/issues/187","id":57486890,"number":187,"title":"Reordering API backends can lead to a lot of backend changes that need publishing","user":{"login":"GUI","id":12112,"avatar_url":"https://avatars.githubusercontent.com/u/12112?v=3","gravatar_id":"","url":"https://api.github.com/users/GUI","html_url":"https://github.com/GUI","followers_url":"https://api.github.com/users/GUI/followers","following_url":"https://api.github.com/users/GUI/following{/other_user}","gists_url":"https://api.github.com/users/GUI/gists{/gist_id}","starred_url":"https://api.github.com/users/GUI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GUI/subscriptions","organizations_url":"https://api.github.com/users/GUI/orgs","repos_url":"https://api.github.com/users/GUI/repos","events_url":"https://api.github.com/users/GUI/events{/privacy}","received_events_url":"https://api.github.com/users/GUI/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":{"login":"GUI","id":12112,"avatar_url":"https://avatars.githubusercontent.com/u/12112?v=3","gravatar_id":"","url":"https://api.github.com/users/GUI","html_url":"https://github.com/GUI","followers_url":"https://api.github.com/users/GUI/followers","following_url":"https://api.github.com/users/GUI/following{/other_user}","gists_url":"https://api.github.com/users/GUI/gists{/gist_id}","starred_url":"https://api.github.com/users/GUI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GUI/subscriptions","organizations_url":"https://api.github.com/users/GUI/orgs","repos_url":"https://api.github.com/users/GUI/repos","events_url":"https://api.github.com/users/GUI/events{/privacy}","received_events_url":"https://api.github.com/users/GUI/received_events","type":"User","site_admin":false},"milestone":null,"comments":1,"created_at":"2015-02-12T16:53:30Z","updated_at":"2015-06-12T04:53:17Z","closed_at":"2015-06-12T04:53:17Z","body":"API backends can be reordered to change their matching order (so you can give certain APIs a higher precedent in how the URL prefixes get matched). However, currently we use a pretty simple implementation for sort order: if there are 50 API backends, then each one will be assigned a matching order number of 1-50. If you decide to reorder item 26 and put it at the bottom, then items 27-50 will all have their sort order change (each one's sort order would be be subtracted by 1). This type of sorting is simple and works well for most apps, but in our case, that means that backends 26-50 suddenly have differences that need to be re-publsished. This is problematic for a couple reasons:\r\n\r\n- For limited admins (with only access to a single agency's APIs), this means that if they resort their API backends, they may actually be impacting the sort order for APIs outside of their agency (since we always resort the entire list of API backends to maintain consistent numbering). While technically this should be fine (since agencies can only really affect ordering within the scope they have permission to), this could still potentially lead to a lot of changes that other agencies suddenly see as needing to be published.\r\n- As a superuser admin that has permissions to all APIs, I don't necessarily want to bulk republish all the API backends if I resort thing, since there may have been other pending changes to API backends that are not ready to go live.\r\n\r\nThis has sort of been nagging at the back of my mind as a potential issue for a while now, but I guess I never wrote this up in an issue. I don't think reordering is super common, but it has come up a couple times in the past week for the first time, so this would be something good to tackle.\r\n\r\nThere are a couple ways I can think to address this:\r\n\r\n- Use a different sorting algorithm that picks integers with large gaps in between them, and then re-sorts by trying to fit new numbers in between existing gaps. For example, each record might have a sort order of 0, 100, 200, 300. Moving the 300 item between 100 and 200 would give that record a sort order of 150. [ranked-model](https://github.com/mixonic/ranked-model#internals) implements this algorithm. It seems a bit complex, and you'd theoretically reach points where you would have to shift numbers around (once all the gaps are gone), but it would significantly cut down on the reordering churn. Unfortunately, the existing gem is for ActiveRecord, and since we're using Mongoid, we'd have to implement this ourselves.\r\n- Use a sorting algorithm based on a linked list. In this way, each record would just keep track of the item next to it. To sort the items, you'd then need to walk each item in order to construct the proper order. [resort](https://github.com/codegram/resort#rationale) implements this algorithm. Linked lists are simpler to implement, but depending on the specifics it may end up really affecting the surrounding records, rather than the record that you actually want to shift. This would certainly lead to a lot less reordering churn, but it may require changes to API backends that you don't have permissions to (since those might be your neighbors). This is also more difficult to sort by with a pure database query (but that may be okay, since we don't need to sort these that frequently). Similarly, this existing gem is for ActiveRecord, and I can't find a similar linked list gem for Mongoid, so we'd have to implement it ourselves."}}