* Clean up javascript.
* Return HTTP 422 instead of HTTP 500 on "you have already voted for
this post" errors.
* In json/xml error responses, return the error message in the `message`
field, not `reason`.
* In json/xml success responses, return the post itself instead of a
plain `{ success: true }` object.
* Simplify code.
* Show backtraces for all users, not just builders.
* Show backtraces only for unexpected server errors (status 5xx), not
for normal client errors (status 4xx).
* Log expected errors at info level (reduce noise in production logs).
Favoriting posts sometimes fails with ActiveRecord::LockWaitTimeout
errors. This happens when a user tries to favorite multiple posts in
short succession. In that case we want the lock to block and wait for
the other favorite to go through, not to immediately fail.
This causes the browser to prefetch the next page in a search, which may
make browsing seem faster to the end user, but it effectively doubles
the load on the server.
Bug: Searching for an aliased tag returns an empty page instead of
showing the results for the real tag.
Cause: The query parsing code runs the search string through
`.mb_chars.downcase` before calling `TagAlias.to_aliased`, so the input
to `to_aliased` is actually a ActiveSupport::Multibyte::Chars object.
This breaks the `aliases[name]` hash lookup because `name` is not a
plain string.
Fixup for c7bcce429.
During single-tag searches we look up the tag once in Post.fast_count
and later on when rendering the wiki excerpt. Doing a raw query here
meant that Rails couldn't cache the query, so it got ran again when
rendering the excerpt.
Using `any?` here translated each lookup into two queries, one to check
if the aliases/implications existed and one to actually load them. Using
`present?` avoids the existence check.
Avoid some queries used in wiki page excerpts:
* Only try to load the artist if the tag is an artist tag.
* Avoid using `exists?` queries for wiki pages.
* Bugfix: don't show wiki excerpts for deleted wikis.
In multi-tag searches, we calculated the tags in the sidebar by sampling
300 random posts from within the search and finding the most frequently
used tags. This meant we were effectively doing two searches on every
page load, one for the actual search and one for the sidebar. This is
not so bad for fast searches, but very bad for slow searches.
Instead, now we calculate the related tags from the current page of
results. This is much faster, at the cost of slightly lower accuracy and
the tag list changing slightly as you browse between pages.
We could use caching here, which would help when browsing between pages,
but we would still have to calculate the tags on the first page load,
which can be very slow in the worst case.
Post.fast_count calls Tag.normalize_query to normalize the tag string
used for the pfc cache key. This slightly improves cache sharing at the
expense of an extra query during tag searches. The extra query isn't
worth it.