Introduction
This gem provides functionality to compress and decompress two different types of objects:
-
a contiguous range or multiple contiguous ranges of integer ID
-
a set of UUID
as a single string.
Both Ruby and Javascript implementations are provided.
Javascript support for Rails is provided by means of a Rails engine (IdPack::Engine
).
Further, for integer ID ranges, it provides serialization of a concept called
sync_str
, which stands for "synchronization string".
sync_str
represents a mapping from ID to timestamp.
It is typically generated on the client side for the server side.
Armed with the sync_str
, the server knows which objects the client requires,
by comparing the timestamps from the sync_str
with the update times of the
corresponding objects from the database, so synchronization could be done with
minimal waste of bandwidth.
Timestamps are really just integers, e.g. Time.now.to_i
.
Installation
There are at least two ways to install this:
-
The quickest way is to
gem install
on the terminal:gem install id_pack
-
If your application has a
Gemfile
, add the following line:gem 'id_pack'
And then execute:
bundle
Usage
To experiment with the code, run bin/console
for an interactive prompt.
require 'id_pack'
IdPacker
To encode/decode a set of IDs:
ids = [5, 6, 21, 23, 25]
encoded_ids = id_packer.encode(ids) #=> "_F~C_P.V"
decoded_ids = id_packer.decode(encoded_ids) #=> [5, 6, 21, 23, 25]
ids == decoded_ids #=> true
To work with sync_str
:
ids_synced_at = {
1 => 1510294889,
2 => 1510292639,
10 => 1510279639,
}
sync_str = id_packer.encode_sync_str(ids_synced_at)
#=> "IwVmAYCYHYE4DYDMsg,IxA,IwVgTCAMQ,ExA,IwZgDBQ,IwBiA,AxA"
decoded_sync_map = id_packer.decode_sync_str(sync_str)
#=> {1=>1510294889, 2=>1510292639, 10=>1510279639}
ids_synced_at == decoded_sync_map
#=> true
Advanced sync_str
usage
IdPacker#decode_sync_str
optionally supports a base_timestamp
:
= 1000
decoded_sync_map2 = id_packer.decode_sync_str(sync_str, )
#=> {1=>1510295889, 2=>1510293639, 10=>1510280639}
= - ids_synced_at.min[1]
decoded_sync_map3 = id_packer.decode_sync_str(sync_str, )
#=> {1=>0, 2=>-2250, 10=>-15250}
= - ids_synced_at.max[1]
decoded_sync_map4 = id_packer.decode_sync_str(sync_str, )
#=> {1=>15250, 2=>13000, 10=>0}
base_timestamp
is typically specified to reverse any normalization of
timestamps done on the client side (not shown in this README).
UuidPacker
uuid_packer = IdPack::UuidPacker.new
uuids = [
'ea8bed36-a73d-4fff-af36-32162274dfd1',
'22347af1-7c60-48e0-8cc5-a30746812267',
'3e514775-bfdb-44f9-92b2-c4c53a7dc89d',
]
To encode/decode a set of UUIDs, first, specify the set of encoding characters:
base_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_'
Also, decide whether we want to preserve the order of the UUIDs:
ordered = true
encoded_uuids = uuid_packer.alphanum_compress(uuids, base_string, ordered)
#=> "Rf2XIjQmNnr_8rzlbLfRV+ZEgWLgxaMxBxIGPo9eLES5E75coyNNSZ8i2_tdxRT4"
decoded_uuids = uuid_packer.alphanum_decompress(encoded_uuids, base_string)
#=> ["ea8bed36-a73d-4fff-af36-32162274dfd1", "22347af1-7c60-48e0-8cc5-a30746812267", "3e514775-bfdb-44f9-92b2-c4c53a7dc89d"]
uuids == decoded_uuids
#=> true
If we don’t care for the order:
ordered = false
unordered_encoded_uuids = uuid_packer.alphanum_compress(uuids, base_string, ordered)
unordered_decoded_uuids = uuid_packer.alphanum_decompress(unordered_encoded_uuids, base_string)
uuids == unordered_decoded_uuids
#=> false
uuids.sort == unordered_decoded_uuids.sort
#=> true
Development
After checking out the repo, run bin/setup
to install dependencies.
Then, run bundle exec rake spec
to run the tests.
You can also run bin/console
for an interactive prompt that will allow you to
experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/riboseinc/id_pack. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.