{ "info": { "author": "Ezhome Engineers", "author_email": "engineers@ezhome.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: Other/Proprietary License", "Operating System :: OS Independent", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "# Flax ID\n\nFlax ID is an algorithm for generating unique distributed ids, made to be used\nat ezHome Inc.\n\nConceptually it belongs to the family of \"Flake ID\" algorithms.\n\nFor an overview of the idea, see, for example:\n\n1. [http://yellerapp.com/posts/2015-02-09-flake-ids.html](http://yellerapp.com/posts/2015-02-09-flake-ids.html)\n\n## Design Goals\n\nWe wanted an algorithm with the following characteristics:\n\n1. Completely distributed, requires no co-ordination\n2. Generates ids that are unique, with very high probability\n3. Generates ids that can be roughly ordered according to the time of creation\n4. Ids have a nice string representation\n5. Works the same across different languages and platforms\n\nMultiple implementations exist but not all of them satisfy the above criteria,\nand the details of implementations vary wildly (most notably in the length and\ncomposition of the data), and we couldn't find a solution that was implemented\nthe same way in different languages.\n\nSome of the candidates considered:\n\n* Python: [simpleflake](https://github.com/SawdustSoftware/simpleflake)\n* Javascript: [flake-idgen](https://www.npmjs.com/package/flake-idgen)\n\nAs a result, we decided to write our own algorithm, which gives us the\nfollowing benefits:\n\n1. We control the exact parameters of the id generation (e.g. bit lengths)\n2. We can describe the algorithm very precisely, which makes writing\nimplementations in different languages straightforward, as opposed to trying\nto decipher the intents of the algorithm creators\n\nWe found inspiration (and some validation) for this approach in this article\nby Firebase:\n[The 2^120 Ways to Ensure Unique Identifiers](https://www.firebase.com/blog/2015-02-11-firebase-unique-identifiers.html)\n\nTODO: Add explanation of what is wrong with UUID (spoiler: mostly ordering).\n\n## Implementation Details\n\n### Composition\n\nThe Flax ID contains 96 bits, of which first 40 bits are the timestamp, and\nthe next 56 bits are random.\nThis gives 2^56 possible unique ids per millisecond.\n\nThe number 96 was chosen on the following grounds:\n\n1. It is divisible by 6, so can be rendered as base64-encoded string without\npadding\n2. It is divisible by 8, so it can be represented as a byte array\n3. It leaves enough room for the random part\n\nWe save some space on the timestamp component by using a custom epoch start\n(we start on 2015-01-01), which allows us to use 40 bits, instead of 42 to\nrepresent the timestamp for the next 30+ years.\n\n\n Here is the structure of the example id:\n\n | 00000 10111001010010101010101001010001111 01110110100000001100101110001011101110011011110111000001 |\n | (padding) timestamp | randomness |\n | 40 | 56 |\n\n (Padding is necessary when there is less than 40 bits in the timestamp, e.g. the elapsed time since the epoch\n is still relatively small)\n\n And here is the rendering with our modified Base64 alphabet:\n\n 000001 011100 101001 010101 010100 101000 111101 110110 100000 001100 101110 001011 101110 011011 110111 000001\n 0 R d K J c x q V B i A i Q r 0\n\n### Representation\n\nThe canonical representation of the Flax ID is Base64-encoded, URL safe string\n(16 characters).\nWe're using the slightly modified Base64 alphabet, which gives us the\nguaranteed lexicographical ordering of the strings thus produced (Firebase does\nthe same)\n\n \"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\"\n\n### The algorithm\n\nThe algorithm is defined as follows:\n\n1. Take a timestamp, as a number of milliseconds since the beginning of our\nepoch\n2. Combine it, by means of left binary shift with 56 random bits\n3. Represent the number as binary string, applying padding, if necessary, so\nthe total number of bits is 96\n4. Encode the binary string using the Base64 alphabet above, taking each 6\nbits to represent a number\n\n## Installation\n\n $ pip install python-flax-id\n\n## Development\n\n### Running tests\n\nAs usual run:\n\n $ make test\n\n### Publishing new release\n\nTo publish new release you need to,\n\n1. Bump version number according to [SemVer](http://semver.org/) in\n `flax_id/__init__.py` file and put a log into *ChangeLog* section below\n2. Wait for your code is tested on Circle CI & merged to `master`\n3. Create new Git tag with version number as `vX.Y.Z` and push it to remote\n4. Publish new release to pypi\n\n#### Git Tag Snippet\n\n git tag -a vX.Y.Z -m 'X.Y.Z Release'\n git push --tags\n\n## Changelog\n\n### 1.0.0 (2018-04-24)\n\n- Initial public release\n\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ezhome/python-flax-id", "keywords": "ezhome flax flax-id", "license": "Other/Proprietary License", "maintainer": "", "maintainer_email": "", "name": "python-flax-id", "package_url": "https://pypi.org/project/python-flax-id/", "platform": "any", "project_url": "https://pypi.org/project/python-flax-id/", "project_urls": { "Homepage": "https://github.com/ezhome/python-flax-id" }, "release_url": "https://pypi.org/project/python-flax-id/1.1.0/", "requires_dist": null, "requires_python": "", "summary": "Python implementation of Flax ID algorithm", "version": "1.1.0" }, "last_serial": 3806665, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "1ee7bea6dfd448c72ca1fa7c2f335d71", "sha256": "80c7ad9d96180e8b14b5bd716bba08baeea3fce20d86d382172902cce158d2d4" }, "downloads": -1, "filename": "python_flax_id-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "1ee7bea6dfd448c72ca1fa7c2f335d71", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6441, "upload_time": "2018-04-24T12:31:28", "url": "https://files.pythonhosted.org/packages/e5/32/de607497c77cb5169eecb79d5b401b85ff52e8c6c6937e8dc42dd7a6c367/python_flax_id-1.0.0-py3-none-any.whl" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "abca7c1c551f9edf96bad530917344c2", "sha256": "28046e02f246071edf66c0ed9e531d3d92fae42e9168ed054188887fbbb46b49" }, "downloads": -1, "filename": "python_flax_id-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "abca7c1c551f9edf96bad530917344c2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9619, "upload_time": "2018-04-25T12:32:09", "url": "https://files.pythonhosted.org/packages/c8/db/1dc3ccfd1d5c3714fe3989c18a03d0f58b1e017d989c6b1ee307fee28531/python_flax_id-1.1.0-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "abca7c1c551f9edf96bad530917344c2", "sha256": "28046e02f246071edf66c0ed9e531d3d92fae42e9168ed054188887fbbb46b49" }, "downloads": -1, "filename": "python_flax_id-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "abca7c1c551f9edf96bad530917344c2", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9619, "upload_time": "2018-04-25T12:32:09", "url": "https://files.pythonhosted.org/packages/c8/db/1dc3ccfd1d5c3714fe3989c18a03d0f58b1e017d989c6b1ee307fee28531/python_flax_id-1.1.0-py3-none-any.whl" } ] }