Fixes#4598.
#4474 made the JSON time conversion no longer invertible, which caused
problems for chat, which uses message timestamp in milliseconds as a key
-- so chat would send a message with ms timestamp x, it would get
encoded as @da x, but then when it went back through the conversion to
milliseconds, it would often (not always) get encoded as x-1.
I still do not fully understand why this is -- and why it doesn't seem
to be a problem with seconds based on cursory testing -- but integer
multiplication and division generally do not invert. And adding a half a
millisecond to the input date before converting it resolves the issue
and makes the functions invertible.
I added a regression test, so hopefully the next courageous adventurer
who winds up here after wondering why +unm looks funny will have a
safeguard against some of the mistakes I made.
Previously, if metadata-store said a graph existed, we'd unconditionally scry
for it. Now, we make sure the graph actually exists, to avoid risking a crash.
No PNG is (sane %t) - the PNG header alone isn't.
This should also be octs, not an atom, as a binary filetype - it works
for PNG purely by coincidence (no valid PNG can end with a sequence of
00 bytes, because they have to end with 00 00 00 00 49 45 4e 44 ae 42 60
82).
Adds a workflow that, on every push to master, will publish new versions
of interface subpackages to the NPM registry if any are available.
Staged to trigger on a test branch for now.
N.B. this boldly assumes that store state will always contain a valid
storage element that will contain gcp and s3 elements. This seems like a
fair assumption.
Adds a 'merge-release' workflow that runs on any push to a release
branch. At present the only job merges the triggering branch to
'ops-tlon'.
Also renames the 'merge' workflow to 'merge-master' to distinguish it
appropriately.
Options here were: make the get-token thread try to return a unit, or
write a different thread to check whether GCP Storage seemed to be
configured and poll on that thread, or move the whole thing into a Gall
app.
The compromise between time-to-implement and overall cleanliness seemed
to be to write a different thread that just checks whether the settings
fields have been poked. Unfortunately this means GcpManager is now a
somewhat hefty JavaScript state machine.
Took out the logic to check whether S3 was configured in GcpManager,
since it was really only there to prevent spamming the console with
500s. If you have both S3 and GCP Storage configured for some reason,
you will now use GCP per the logic in useStorage.
s3.credentials is always set, but the fields are all '' if s3 is not
configured. So prior to this change, if the user had configured an
active bucket, they would always be shown an upload dialog even if they
had no storage configured.
GcpApi now acts like other APIs.
Since GcpManager can no longer get at the token exipry by inspecting the
raw update, it must depend on the global store instead. This also means
it can check whether the user has configured S3, and not try to refresh
the token in that case.
In the case where no storage is configured, this will spam the console
with request failures since the thread returns 500 if there is no token.
Perhaps this is a good argument for making the thread return a unit.