| 245 | } |
| 246 | |
| 247 | std::vector<TopicId> SessionManager::commitChunks(std::vector<std::pair<TopicId, TopicChunk>> chunks) { |
| 248 | auto changed = data_engine_.commitChunks(std::move(chunks)); |
| 249 | if (changed.empty()) { |
| 250 | return changed; |
| 251 | } |
| 252 | // Run eager filters over the freshly committed input, then notify both the raw |
| 253 | // and the derived output topics so filtered curves refresh. (Loaded files keep |
| 254 | // full history, so there is no retention race on this path.) |
| 255 | const std::vector<TopicId> derived_outputs = |
| 256 | processor_service_ ? processor_service_->advanceOnCommit(changed) : std::vector<TopicId>{}; |
| 257 | |
| 258 | QVector<TopicId> ids; |
| 259 | ids.reserve(static_cast<qsizetype>(changed.size() + derived_outputs.size())); |
| 260 | for (const TopicId id : changed) { |
| 261 | ids.push_back(id); |
| 262 | } |
| 263 | for (const TopicId id : derived_outputs) { |
| 264 | ids.push_back(id); |
| 265 | } |
| 266 | refreshDatasetMinTimestampsForTopics(ids); // also resets global_min_cache_ |
| 267 | emit samplesIngested(std::move(ids), /*live=*/false); |
| 268 | return changed; |
| 269 | } |
| 270 | |
| 271 | void SessionManager::notifyIngest(QVector<TopicId> ids, bool live) { |
| 272 | if (ids.isEmpty() && !live) { |