"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InMemoryEventsStore = void 0;
var tslib_1 = require("tslib");
var base_events_store_1 = require("./base-events-store");
var InMemoryEventsStore = /** @class */ (function (_super) {
    tslib_1.__extends(InMemoryEventsStore, _super);
    function InMemoryEventsStore() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.finalizedSequences = {};
        _this.sequences = {};
        _this.sequenceId = 0;
        _this.emptyFilteredCount = 0;
        return _this;
    }
    InMemoryEventsStore.prototype.resetCurrentSequence = function (sessionId) {
        this.sequences[sessionId] = [];
    };
    InMemoryEventsStore.prototype.addSequence = function (sessionId) {
        var sequenceId = this.sequenceId++;
        var events = tslib_1.__spreadArray([], tslib_1.__read(this.sequences[sessionId]), false);
        this.finalizedSequences[sequenceId] = { sessionId: sessionId, events: events };
        this.resetCurrentSequence(sessionId);
        return { sequenceId: sequenceId, events: events, sessionId: sessionId };
    };
    // Sampled (1 in 100) debug log so we can observe whether the store-layer guards
    // are actually catching cases that would otherwise hit the empty-body 400 path on
    // the server. Logged at debug, not warn — this is operational telemetry for
    // post-deploy verification, not a customer-actionable warning. Per-store-instance
    // counter rather than Math.random keeps the first hit deterministic for tests.
    InMemoryEventsStore.prototype.maybeLogEmptyFiltered = function (source) {
        if (this.emptyFilteredCount++ % 100 === 0) {
            this.loggerProvider.debug("Filtered empty session replay sequence at ".concat(source, " (in-memory store)"));
        }
    };
    InMemoryEventsStore.prototype.getSequencesToSend = function () {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var result, _a, _b, _c, sequenceId, _d, sessionId, events;
            var e_1, _e;
            return tslib_1.__generator(this, function (_f) {
                result = [];
                try {
                    for (_a = tslib_1.__values(Object.entries(this.finalizedSequences)), _b = _a.next(); !_b.done; _b = _a.next()) {
                        _c = tslib_1.__read(_b.value, 2), sequenceId = _c[0], _d = _c[1], sessionId = _d.sessionId, events = _d.events;
                        if (events.length === 0) {
                            // Prune in-place for consistency with the IDB store: by construction we
                            // never write empty sequences anymore, so any empty entry is unambiguously
                            // stale residue. Without the delete, every subsequent getSequencesToSend
                            // would re-iterate the empty entry and re-fire the sampled log, producing
                            // repeated noise that's indistinguishable from active bug occurrences.
                            this.maybeLogEmptyFiltered('getSequencesToSend');
                            delete this.finalizedSequences[Number(sequenceId)];
                            continue;
                        }
                        result.push({ sequenceId: Number(sequenceId), sessionId: sessionId, events: events });
                    }
                }
                catch (e_1_1) { e_1 = { error: e_1_1 }; }
                finally {
                    try {
                        if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
                    }
                    finally { if (e_1) throw e_1.error; }
                }
                return [2 /*return*/, result];
            });
        });
    };
    InMemoryEventsStore.prototype.storeCurrentSequence = function (sessionId) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var buffered;
            return tslib_1.__generator(this, function (_a) {
                buffered = this.sequences[sessionId];
                if (!buffered) {
                    return [2 /*return*/, undefined];
                }
                if (buffered.length === 0) {
                    // Slot exists but is empty (e.g. drained by a prior storeCurrentSequence then
                    // re-flushed before any new event landed). Don't finalize a zero-event row.
                    this.maybeLogEmptyFiltered('storeCurrentSequence');
                    return [2 /*return*/, undefined];
                }
                return [2 /*return*/, this.addSequence(sessionId)];
            });
        });
    };
    InMemoryEventsStore.prototype.addEventToCurrentSequence = function (sessionId, event) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            var sequenceReturn;
            return tslib_1.__generator(this, function (_a) {
                if (!this.sequences[sessionId]) {
                    this.resetCurrentSequence(sessionId);
                }
                // shouldSplitEventsList can return true with an empty buffer when a single
                // incoming event is larger than MAX_EVENT_LIST_SIZE (2 MB) — the size-constraint
                // branch fires regardless of current length. Don't finalize a zero-event sequence
                // (the SR-4284 root cause); just hold the incoming event in the buffer.
                // shouldSplitEventsList's time-elapsed branch only fires when events.length > 0
                // (see base-events-store.ts), so calling it on an empty buffer has no side effects.
                if (this.shouldSplitEventsList(this.sequences[sessionId], event)) {
                    if (this.sequences[sessionId].length === 0) {
                        this.maybeLogEmptyFiltered('addEventToCurrentSequence');
                    }
                    else {
                        sequenceReturn = this.addSequence(sessionId);
                    }
                }
                this.sequences[sessionId].push(event);
                return [2 /*return*/, sequenceReturn];
            });
        });
    };
    InMemoryEventsStore.prototype.storeSendingEvents = function (sessionId, events) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            return tslib_1.__generator(this, function (_a) {
                this.finalizedSequences[this.sequenceId] = { sessionId: sessionId, events: events };
                return [2 /*return*/, this.sequenceId++];
            });
        });
    };
    InMemoryEventsStore.prototype.cleanUpSessionEventsStore = function (_sessionId, sequenceId) {
        return tslib_1.__awaiter(this, void 0, void 0, function () {
            return tslib_1.__generator(this, function (_a) {
                if (sequenceId !== undefined) {
                    delete this.finalizedSequences[sequenceId];
                }
                return [2 /*return*/];
            });
        });
    };
    return InMemoryEventsStore;
}(base_events_store_1.BaseEventsStore));
exports.InMemoryEventsStore = InMemoryEventsStore;
//# sourceMappingURL=events-memory-store.js.map