2.0.0 • Published 4 months ago

in-memory-tracker v2.0.0

Weekly downloads
-
License
MIT
Repository
-
Last release
4 months ago

In-Memory Tracker

In-Memory Tracker is a lightweight, standalone JavaScript module designed for the deduplication, deferral, and change detection of events using an in-memory store. It is ideal for scenarios such as alert systems or logging tools—where you need fine‑grained control over duplicate events and adjustments when event details change.

Features

  • In-Memory Storage:
    Manage event states entirely in memory, eliminating the need for external databases.

  • Three-Level Identification:
    Events are now tracked by a combination of:

    • Category: A high-level grouping (e.g. authentication).
    • ID: A specific identifier within that category (e.g. a user’s ID).
    • Details: Detailed information about the event (e.g. IP address, failure reason).
      A composite key (computed as an MD5 hash from category and ID) is used to uniquely track each record.
  • Event Deduplication and Change Detection:
    A details hash (computed from the sorted event details JSON) lets the tracker:

    • Detect changes in event details and reset the counter accordingly.
    • Increase the counter for multiple events with identical details.
  • Deferral Mechanism:
    Configurable limits and deferral intervals let you defer events that exceed a specified threshold. Deferred events are later eligible for re‑processing.

  • Deferred Events Lookup:
    Easily retrieve a list of deferred events, optionally filtered by category and/or id.

  • Flexible Integration:
    Clear result types (immediate, deferred, or ignored) let your application decide what to do next.

Installation

Install the module via npm:

npm install in-memory-tracker

Usage

Below is a real‑world example that simulates failed login attempts within an authentication system. In this scenario:

  • Category: Represents the system (e.g. authentication).
  • ID: Represents the specific user (e.g. user:john_doe).
  • Details: Include attributes such as the IP address and a failure reason.
const InMemoryTracker = require('in-memory-tracker');

// Create a tracker instance with custom options.
const tracker = new InMemoryTracker({
  limit: 3,                         // Allow up to 3 immediate events before deferring.
  deferInterval: 10 * 1000,         // 10 seconds until a deferred event can be re‑processed.
  expireTime: 60 * 60 * 1000          // Reset the event count after 1 hour.
});

// Real-world scenario: Failed login attempts.
// Category represents the system ("authentication") and id represents a specific user.
function simulateFailedLogin(user, ip) {
  // Details include the IP address and the failure reason.
  const details = {
    ipAddress: ip,
    failureReason: 'Invalid password'
  };

  // Track a failed login attempt.
  const result = tracker.trackEvent('authentication', user, details);

  if (result.type === 'immediate') {
    console.log(`[Immediate] Login attempt for ${user} from ${ip} recorded. Count: ${result.data.count}`);
  } else if (result.type === 'deferred') {
    console.log(`[Deferred] Too many login attempts for ${user} from ${ip}. Notification scheduled at ${new Date(result.data.scheduledSendAt).toLocaleTimeString()}`);
  } else { // 'ignored'
    console.log(`[Ignored] Login attempt for ${user} from ${ip} ignored (already deferred).`);
  }
}

// Simulate several failed login attempts for the user 'user:john_doe'.
const user = 'user:john_doe';
const ip = '192.168.1.101';

// The first three events are processed immediately.
simulateFailedLogin(user, ip);
simulateFailedLogin(user, ip);
simulateFailedLogin(user, ip);

// The fourth event exceeds the limit and triggers deferral.
simulateFailedLogin(user, ip);

// After the defer interval has passed, process the deferred events.
setTimeout(() => {
  const deferredEvents = tracker.processDeferredEvents();
  if (deferredEvents.length > 0) {
    console.log('Processing deferred events:');
    deferredEvents.forEach(ev => {
      console.log(`Deferred event for ${ev.category} "${ev.id}" with details:`, ev.details);
    });
  } else {
    console.log('No deferred events ready for processing.');
  }

  // Optionally, retrieve deferred events for monitoring.
  const allDeferred = tracker.getDeferredEvents({ category: 'authentication', id: user });
  if (allDeferred.length > 0) {
    console.log('Currently deferred events:', allDeferred);
  }
}, 11 * 1000); // Wait slightly longer than the deferInterval to allow processing.

API

Constructor

new InMemoryTracker(options);

Options

  • limit (number, default: 5):
    Maximum number of immediate events allowed before deferral.

  • deferInterval (number, default: 60 60 1000):
    Time (in milliseconds) to wait before a deferred event becomes eligible for re‑processing.

  • expireTime (number, default: 24 60 60 * 1000):
    Time (in milliseconds) after which the event count is reset.

  • autoPurge (boolean, default: true):
    When enabled, expired records are automatically purged each time an event is tracked.

Methods

trackEvent(category, id, details)

Records an incoming event.

  • Parameters:

    • category (string): The high-level category (e.g. "authentication").
    • id (string): The specific identifier within the category (e.g. user id).
    • details (object): Additional event details (e.g. { ipAddress, failureReason }).
  • Behavior:

    • If no record exists, a new record is created with count set to 1.
    • If a record exists and the event details have changed, the record is reset.
    • If the record exists with unchanged details and is within the expire window, the counter increments.
      • Returns immediate if the count is within the limit.
      • Returns deferred and schedules re‑processing if the count exceeds the limit.
      • Returns ignored if an event is already deferred.
  • Returns:
    An object with:

    • type: "immediate", "deferred", or "ignored".
    • data: Includes category, id, details, count, and (if applicable) scheduledSendAt.

processDeferredEvents()

Processes deferred events that are eligible for re‑processing (based on the defer interval).

  • Returns:
    An array of events ready for processing, each containing:
    • The composite key.
    • The category and id.
    • The event details.

getDeferredEvents(filter)

Retrieves deferred events, optionally filtered by category and/or id.

  • Parameters:

    • filter (object, optional):
      • category (string): Filter events by category.
      • id (string): Filter events by id.
  • Returns:
    An array of deferred event objects, each including:

    • The composite key.
    • The category and id.
    • The event details.
    • The scheduled send time (scheduledSendAt) for processing.

Contributing

Contributions, improvements, and bug fixes are welcome! Feel free to fork the repository and open pull requests.

License

This project is licensed under the MIT License. See the LICENSE file for details.

2.0.0

4 months ago

1.3.0

4 months ago

1.2.5

4 months ago

1.2.4

4 months ago

1.2.3

4 months ago

1.2.2

4 months ago

1.2.1

4 months ago

1.2.0

4 months ago

1.1.0

4 months ago

1.0.1

4 months ago

1.0.0

4 months ago