using Apache.IoTDB;
using Apache.IoTDB.DataStructure;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.IoTDBProvider
{
///
/// IoTDB数据源
///
public class IoTDBProvider : IIoTDBProvider, IDisposable
{
private readonly IoTDBOptions _options;
private readonly SessionPool _sessionPool;
private static readonly ConcurrentDictionary _metadataCache = new();
public IoTDBProvider(IOptions options)
{
_options = options.Value;
_sessionPool = new SessionPool(
_options.ClusterList,
_options.UserName,
_options.Password,
_options.PoolSize);
_sessionPool.Open(false).Wait();
}
///
/// 获取设备元数据
///
///
///
private DeviceMetadata GetMetadata() where T : IoTEntity
{
return _metadataCache.GetOrAdd(typeof(T), type =>
{
var metadata = new DeviceMetadata();
foreach (var prop in type.GetProperties())
{
var attr = prop.GetCustomAttribute();
if (attr != null)
{
metadata.Tags.Add(prop.Name);
}
else if (prop.Name != nameof(IoTEntity.Timestamp))
{
metadata.Measurements.Add(prop.Name);
}
}
return metadata;
});
}
///
/// 插入数据
///
///
///
///
public async Task InsertAsync(T entity) where T : IoTEntity
{
var metadata = GetMetadata();
var storageGroup = DevicePathBuilder.BuildStorageGroupPath();
await EnsureStorageGroupCreated(storageGroup);
var tablet = BuildTablet(new[] { entity }, metadata);
await _sessionPool.InsertAlignedTabletAsync(tablet);
}
///
/// 批量插入数据
///
///
///
///
public async Task BatchInsertAsync(IEnumerable entities) where T : IoTEntity
{
var metadata = GetMetadata();
var storageGroup = DevicePathBuilder.BuildStorageGroupPath();
await EnsureStorageGroupCreated(storageGroup);
var batchSize = 1000;
var batches = entities.Chunk(batchSize);
foreach (var batch in batches)
{
var tablet = BuildTablet(batch, metadata);
await _sessionPool.InsertAlignedTabletAsync(tablet);
}
}
///
/// 构建表模型
///
///
///
///
///
private Tablet BuildTablet(IEnumerable entities, DeviceMetadata metadata) where T : IoTEntity
{
var devicePath = DevicePathBuilder.BuildDevicePath(entities.First());
var timestamps = new List();
var values = new List>();
foreach (var entity in entities)
{
timestamps.Add(entity.Timestamp);
var rowValues = new List