Repository navigation
[python] Restore the process-wide FileIO cache of RESTTokenFileIO - #10552
Merged
JingsongLi merged 1 commit intoOct 14, 2026
Merged
Conversation
apache#9715 gave each RESTTokenFileIO its own TTLCache(maxsize=1), so that tables in different buckets that receive the same token stop sharing one bucket-bound OssFileIO. With one entry per instance, a token refresh releases the previous FileIO while streams opened with the still valid previous credentials keep using it, which crashed Jindo readers before apache#10536, and every RESTTokenFileIO object builds its own FileIO and Jindo client. Share one cache across instances again (1000 entries, 10 hours, like Java's FILE_IO_CACHE). Key it by the token plus the table path and catalog options that FileIO.get builds the FileIO from, which keeps buckets apart, and expire entries 10 hours after their last use like Java's expireAfterAccess. Also align the continuation line flagged by flake8 (E127) in jindo_file_system_test.py, as apache#10550 does.
Contributor
|
+1 |
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
#9715 replaced the process-wide FileIO cache of
RESTTokenFileIO(1000 entries shared by all instances, as in Java'sFILE_IO_CACHE) with aTTLCache(maxsize=1)per instance. The goal was to stop two tables in different buckets that receive the same token from sharing one bucket-boundOssFileIO(review comment).With one entry per instance, a token refresh evicts the previous
FileIOat the moment of the refresh. Tokens are refreshed while they still have up to one hour left, so streams opened with the previous credentials are still valid and often still open. With the Jindo backend, releasing thatFileIOfreed the native store under those streams, and the process crashed with SIGSEGV on their next read, seek, write or close. Readers that hold only a stream hit this: Avro, BLOB, Parquet/ORC by row group, the bitmap and B-tree indexes. Long-running readers crashed this way. #10536 makes Jindo streams pin their filesystem, which removes the crash, but the cache still drops aFileIOthat is in use at every refresh, and eachRESTTokenFileIOobject builds its ownFileIOand Jindo client.This pull request restores the process-wide cache and keeps what #9715 fixed:
TTLCacheshared by all instances, 1000 entries and 10 hours as before [python] Use conditional OSS puts for atomic metadata writes #9715. A refresh adds an entry for the new token and leaves the previousFileIOin place.FileIO.getbuilds theFileIOfrom. The same token on another bucket, or with anotherfs.oss.impl, gets a separateFileIO.expireAfterAccess. AFileIOin use is no longer replaced every 10 hours, and the previous token'sFileIOis released 10 hours after its last use, long after its credentials expired.RESTTokenFileIOobjects of one table in one process share oneFileIO. Eight objects for one table built 8 Jindo clients before (16 after one refresh) and build 1 now (2 after one refresh).The per-instance lock still serializes token refresh and lookup for one object. The shared cache has its own lock, and a missing
FileIOis created under it, so concurrent lookups build one. The keep-alive comment injindo_file_system_handler.pythat named themaxsize=1eviction is updated. This pull request also carries the one-line flake8 fix of #10550 so its CI can pass before that merges; the identical hunks merge cleanly in either order.Tests
rest_token_file_io_test.pytry_to_refresh_tokenwith less than one hour left, and the fake stream, like a pyjindo stream, does not keep itsFileIOalive. On master this fails with "use-after-free".FileIO; a realOssFileIOkeeps its own bucket.FileIO, and concurrent lookups create one.test_pickle_serializationnow expects the unpickled copy to reuse the process-wide cache.jindo_file_system_test.py: a refresh throughOssFileIOandJindoFileSystemHandlerwith a fake pyjindo keeps the previous handler alive, its stream keeps reading, and two objects share one client.dev/cfg.iniover the package passes.Verified with JindoSDK
pyjindosdk 6.10.4, pyarrow 19.0.1, Python 3.11, against a local OSS-compatible server, 3 runs per cell. "without #10536" uses
jindo_file_system_handler.pyfrom before #10536, to show what the cache change does on its own.Streams opened through
RESTTokenFileIO.new_input_stream/new_output_streamon a 4 MiB object:try_to_refresh_token(token issued with 1 h + 2 s left)FileIOidle past the TTL (shortened to 1 s) while a stream is openpypaimon table reads and writes. The table is written with
FileSystemCatalogand read or written through aFileStoreTableon aRESTTokenFileIO, whose tokens are issued with 1 h + 2 s left, so a refresh happens every 2 s:Fork behavior is unchanged. A forked child hangs in
JindoFileSystem.openonce the parent has used pyjindo, on master and with this change, whether the child reads through the inheritedRESTTokenFileIOor a new one; it reads normally when the parent never used pyjindo. Withfs.oss.impl=legacythe child reads normally in every case.The cache alone does not cover a stream that is held past the 10 hour TTL while nothing uses its
FileIO(the TTL row above); #10536 covers that.API and Format
No public API or storage format change.
Documentation
No.