Fix RpcDataSet deadlock, timezone compatibility, column index issues, and deprecation cleanup#48
Fix RpcDataSet deadlock, timezone compatibility, column index issues, and deprecation cleanup#48CritasWang wants to merge 1 commit intomainfrom
Conversation
- Add async NextAsync()/FetchResultsAsync() to RpcDataSet, mark sync Next() as obsolete - Add HasNextAsync() to SessionDataSet for non-blocking iteration - Fix TimeZoneNotFoundException by adding IANA-to-Windows timezone mapping - Fix GetDateByTsBlockColumnIndex/GetIntByTsBlockColumnIndex for Time column (index -1) - Fix RowRecord obsolete constructor usage in RpcDataSet.GetRow() and IoTDBCommand - Migrate all samples from deprecated SessionPool(host,port,poolSize) to Builder pattern - Migrate all samples from deprecated RowRecord 3-arg constructor to 4-arg with TSDataType
There was a problem hiding this comment.
Pull request overview
This PR addresses four critical bugs in the C# IoTDB client library and modernizes all sample code to use non-deprecated APIs. The changes resolve deadlock issues in asynchronous operations, fix timezone compatibility problems on Windows, correct column index handling for timestamp fields, and ensure proper type information is passed when constructing RowRecord objects.
Changes:
- Fixed
RpcDataSet.Next()deadlock by introducing proper async methods (NextAsync(),FetchResultsAsync(),HasNextAsync()) - Added timezone compatibility layer to handle IANA/Windows timezone ID differences
- Fixed
-1column index handling for timestamp fields inGetDate()andGetInt()methods - Updated
RowRecordconstructor calls throughout to includeTSDataTypeinformation
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Apache.IoTDB/SessionPool.cs | Updated to use new HasNextAsync() method |
| src/Apache.IoTDB/DataStructure/SessionDataSet.cs | Added HasNextAsync() and marked sync HasNext() as obsolete |
| src/Apache.IoTDB/DataStructure/RpcDataSet.cs | Implemented async methods, timezone mapping, timestamp column index fix, and RowRecord constructor update |
| src/Apache.IoTDB.Data/IoTDBDataReader.cs | Added pragma directives to suppress obsolete warnings for required sync calls |
| src/Apache.IoTDB.Data/IoTDBCommand.cs | Updated BindParamters() to collect and pass TSDataType list |
| samples/Apache.IoTDB.Samples/*.cs | Migrated all sample code to use Builder pattern, 4-arg RowRecord constructor, and HasNextAsync() |
| Apache-IoTDB-Client-CSharp-UserCase/Program.cs | Updated to use HasNextAsync() |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| List<string> measurementList = new List<string>(); | ||
| List<TSDataType> dataTypeList = new List<TSDataType>(); |
There was a problem hiding this comment.
These two new lists are populated inside the loop but only when localfield != null. If the loop encounters null fields, the lists will have mismatched lengths compared to fieldList, which could lead to incorrect RowRecord construction. Consider adding corresponding entries for null fields or document why this is safe.
| } | ||
| } | ||
|
|
||
| return TimeZoneInfo.Local; |
There was a problem hiding this comment.
Falling back to TimeZoneInfo.Local when the requested timezone cannot be found may lead to incorrect time conversions. Consider throwing a more informative exception or logging a warning to alert users that their specified timezone could not be resolved.
| return TimeZoneInfo.Local; | |
| throw new TimeZoneNotFoundException($"The specified time zone ID '{zoneId}' could not be found on this system."); |
| break; | ||
| case TSDataType.TIMESTAMP: | ||
| localfield = null; | ||
| timestamp = GetLong(columnName); |
There was a problem hiding this comment.
timestamp in initialize RowRecord is not valid because it accepts any column of the timestamp type. If the data contains another column of the timestamp type, an error will occur.
Summary / 概述
Fix four bugs in the C# client library and clean up all deprecated API usages in samples.
修复 C# 客户端库中的四个 Bug,并清理示例代码中所有已废弃 API 的使用。
Bug Fixes / Bug 修复
1. RpcDataSet.Next() deadlock / RpcDataSet.Next() 死锁
Next()internally calledClose().Wait()andFetchResults()with synchronous blocking, which causes deadlocks when the underlying Thrift async calls capture a synchronization context.Next()内部通过Close().Wait()和FetchResults()进行同步阻塞调用,当底层 Thrift 异步调用捕获同步上下文时会导致死锁。Fix: Added
NextAsync()andFetchResultsAsync()as proper async methods. The oldNext()is preserved but marked[Obsolete]for backward compatibility. AddedHasNextAsync()toSessionDataSet.修复: 新增
NextAsync()和FetchResultsAsync()作为正确的异步方法。旧的Next()保留但标记为[Obsolete]以保证向后兼容。在SessionDataSet上新增HasNextAsync()。2. GetDate("Time") index out of range / GetDate("Time") 索引越界
When calling
GetDate("Time")orGetInt("Time"), the TsBlock column index resolves to-1(the special timestamp marker), butGetDateByTsBlockColumnIndexandGetIntByTsBlockColumnIndexdid not handle this case.调用
GetDate("Time")或GetInt("Time")时,TsBlock 列索引解析为-1(时间戳特殊标记),但GetDateByTsBlockColumnIndex和GetIntByTsBlockColumnIndex未处理此情况。Fix: Added
-1index handling to return the timestamp value from_curTsBlock.GetTimeByIndex().修复: 添加了
-1索引处理,从_curTsBlock.GetTimeByIndex()返回时间戳值。3. TimeZoneNotFoundException on Windows / Windows 上时区异常
SessionPool.BuilderdefaultszoneIdto"Asia/Shanghai"(IANA format), butTimeZoneInfo.FindSystemTimeZoneById()on Windows expects Windows timezone IDs like"China Standard Time", causingTimeZoneNotFoundException.SessionPool.Builder默认zoneId为"Asia/Shanghai"(IANA 格式),但 Windows 上的TimeZoneInfo.FindSystemTimeZoneById()期望 Windows 时区 ID(如"China Standard Time"),导致TimeZoneNotFoundException。Fix: Added
FindTimeZoneSafe()with an IANA-to-Windows timezone mapping dictionary as fallback.修复: 新增
FindTimeZoneSafe()方法,内置 IANA 到 Windows 时区映射字典作为回退。4. RowRecord obsolete constructor / RowRecord 废弃构造函数
RpcDataSet.GetRow()andIoTDBCommand.BindParamters()used the deprecatedRowRecord(long, List<object>, List<string>)constructor withoutTSDataTypeinformation.RpcDataSet.GetRow()和IoTDBCommand.BindParamters()使用了不带TSDataType信息的废弃构造函数RowRecord(long, List<object>, List<string>)。Fix: Both now collect
List<TSDataType>and use the 4-arg constructor.修复: 两处均改为收集
List<TSDataType>并使用 4 参数构造函数。Deprecation Cleanup / 废弃 API 清理
Migrated all
new SessionPool(host, port, poolSize)toSessionPool.Builderpattern across all sample filesMigrated all
new RowRecord(timestamp, values, measures)to 4-arg constructor withList<TSDataType>across all sample filesUpdated all
HasNext()calls toawait HasNextAsync()in samplesAdded
#pragma warning disable CS0618inIoTDBDataReaderwhere syncHasNext()is required by the ADO.NETDbDataReader.Read()interface将所有示例文件中的
new SessionPool(host, port, poolSize)迁移为SessionPool.Builder模式将所有示例文件中的
new RowRecord(timestamp, values, measures)迁移为带List<TSDataType>的 4 参数构造函数将示例中所有
HasNext()调用更新为await HasNextAsync()在
IoTDBDataReader中因 ADO.NETDbDataReader.Read()接口要求同步调用,添加了#pragma warning disable CS0618Files Changed / 变更文件
Library / 库代码:
src/Apache.IoTDB/DataStructure/RpcDataSet.cs— async methods, timezone fix, column index fix, GetRow fixsrc/Apache.IoTDB/DataStructure/SessionDataSet.cs— HasNextAsync()src/Apache.IoTDB/SessionPool.cs— use HasNextAsync() in CheckTimeSeriesExistsAsyncsrc/Apache.IoTDB.Data/IoTDBCommand.cs— RowRecord with TSDataTypesrc/Apache.IoTDB.Data/IoTDBDataReader.cs— pragma suppress for sync HasNext()Samples / 示例代码:
SessionPoolTest.*.csfiles — Builder pattern, RowRecord 4-arg, HasNextAsyncTableSessionPoolTest.cs,SessionPoolTest.Utils.cs— HasNextAsyncApache-IoTDB-Client-CSharp-UserCase/Program.cs— HasNextAsynclink: #47