forge-sql-orm 2.1.3 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -0
- package/dist/ForgeSQLORM.js +598 -2
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +601 -5
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/SystemTables.d.ts +5039 -0
- package/dist/core/SystemTables.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +72 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -0
- package/package.json +4 -3
- package/src/core/SystemTables.ts +313 -1
- package/src/webtriggers/applyMigrationsWebTrigger.ts +5 -3
- package/src/webtriggers/index.ts +1 -0
- package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +305 -0
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- ✅ **Custom Drizzle Driver** for direct integration with @forge/sql
|
|
20
20
|
- ✅ **Local Cache System (Level 1)** for in-memory query optimization within single resolver invocation scope
|
|
21
21
|
- ✅ **Global Cache System (Level 2)** with cross-invocation caching, automatic cache invalidation and context-aware operations (using [@forge/kvs](https://developer.atlassian.com/platform/forge/storage-reference/storage-api-custom-entities/) )
|
|
22
|
+
- ✅ **Memory Usage Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
|
|
22
23
|
- ✅ **Type-Safe Query Building**: Write SQL queries with full TypeScript support
|
|
23
24
|
- ✅ **Supports complex SQL queries** with joins and filtering using Drizzle ORM
|
|
24
25
|
- ✅ **Advanced Query Methods**: `selectFrom()`, `selectDistinctFrom()`, `selectCacheableFrom()`, `selectDistinctCacheableFrom()` for all-column queries with field aliasing
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
### 🔒 Advanced Features
|
|
64
65
|
- [Optimistic Locking](#optimistic-locking)
|
|
65
66
|
- [Query Analysis and Performance Optimization](#query-analysis-and-performance-optimization)
|
|
67
|
+
- [Memory Usage Monitoring](#memory-usage-monitoring)
|
|
66
68
|
- [Date and Time Types](#date-and-time-types)
|
|
67
69
|
|
|
68
70
|
### 🛠️ Development Tools
|
|
@@ -79,6 +81,7 @@
|
|
|
79
81
|
- [Query Analysis Example](examples/forge-sql-orm-example-query-analyses)
|
|
80
82
|
- [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker)
|
|
81
83
|
- [Checklist Example](examples/forge-sql-orm-example-checklist)
|
|
84
|
+
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` memory monitoring
|
|
82
85
|
|
|
83
86
|
### 📚 Reference
|
|
84
87
|
- [ForgeSqlOrmOptions](#forgesqlormoptions)
|
|
@@ -95,6 +98,7 @@
|
|
|
95
98
|
- [Global Cache System (Level 2)](#global-cache-system-level-2) - Cross-invocation persistent caching
|
|
96
99
|
- [Local Cache System (Level 1)](#local-cache-operations-level-1) - In-memory invocation caching
|
|
97
100
|
- [Optimistic Locking](#optimistic-locking) - Data consistency
|
|
101
|
+
- [Memory Usage Monitoring](#memory-usage-monitoring) - Memory-intensive query detection
|
|
98
102
|
- [Migration Tools](#web-triggers-for-migrations) - Database migrations
|
|
99
103
|
- [Query Analysis](#query-analysis-and-performance-optimization) - Performance optimization
|
|
100
104
|
|
|
@@ -103,6 +107,7 @@
|
|
|
103
107
|
- [Optimistic Locking Example](examples/forge-sql-orm-example-optimistic-locking) - Real-world conflict handling
|
|
104
108
|
- [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker) - Complex relationships
|
|
105
109
|
- [Checklist Example](examples/forge-sql-orm-example-checklist) - Jira integration
|
|
110
|
+
- [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching with memory monitoring
|
|
106
111
|
|
|
107
112
|
## Usage Approaches
|
|
108
113
|
|
|
@@ -2015,6 +2020,206 @@ This analysis provides insights into:
|
|
|
2015
2020
|
- Resource usage at each step
|
|
2016
2021
|
- Performance optimization opportunities
|
|
2017
2022
|
|
|
2023
|
+
## Memory Usage Monitoring
|
|
2024
|
+
|
|
2025
|
+
[↑ Back to Top](#table-of-contents)
|
|
2026
|
+
|
|
2027
|
+
Forge-SQL-ORM provides automated memory usage monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
|
|
2028
|
+
|
|
2029
|
+
### Why Memory Monitoring is Critical
|
|
2030
|
+
|
|
2031
|
+
Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow query detection (which is available in the Forge Developer Console), there's **no built-in way to monitor memory usage** of your queries. This monitoring system fills that gap by:
|
|
2032
|
+
|
|
2033
|
+
- **Detecting memory-intensive queries** before they hit the 16 MiB limit
|
|
2034
|
+
- **Providing detailed memory metrics** including average and maximum memory usage
|
|
2035
|
+
- **Showing execution plans** to help optimize memory consumption
|
|
2036
|
+
- **Configurable thresholds** to match your application's memory requirements
|
|
2037
|
+
- **Scheduled monitoring** via Forge scheduler triggers
|
|
2038
|
+
|
|
2039
|
+
### Overview
|
|
2040
|
+
|
|
2041
|
+
The memory monitoring system:
|
|
2042
|
+
- **Automatically detects memory-intensive queries** based on configurable memory thresholds
|
|
2043
|
+
- **Provides detailed memory metrics** including execution time, memory usage, and execution plans
|
|
2044
|
+
- **Logs memory issues** to the Forge Developer Console for easy debugging
|
|
2045
|
+
- **Supports scheduled monitoring** via Forge scheduler triggers
|
|
2046
|
+
- **Filters out system queries** to focus on your application's performance
|
|
2047
|
+
|
|
2048
|
+
### Key Features
|
|
2049
|
+
|
|
2050
|
+
- **Memory-Focused Monitoring**: Primary focus on memory usage with configurable thresholds
|
|
2051
|
+
- **Atlassian 16 MiB Limit Awareness**: Designed specifically for Forge SQL's memory constraints
|
|
2052
|
+
- **Execution Plan Analysis**: Shows detailed query plans to help optimize memory consumption
|
|
2053
|
+
- **Configurable Thresholds**: Set custom memory usage thresholds (default: 4MB warning)
|
|
2054
|
+
- **Automatic Filtering**: Excludes system queries (`Use`, `Set`, `Show`) and empty queries
|
|
2055
|
+
- **Scheduled Monitoring**: Run automatically on configurable intervals
|
|
2056
|
+
|
|
2057
|
+
### Basic Usage
|
|
2058
|
+
|
|
2059
|
+
#### 1. Import the Trigger
|
|
2060
|
+
|
|
2061
|
+
```typescript
|
|
2062
|
+
import ForgeSQL, { topSlowestStatementLastHourTrigger } from "forge-sql-orm";
|
|
2063
|
+
```
|
|
2064
|
+
|
|
2065
|
+
#### 2. Create a Scheduler Function
|
|
2066
|
+
|
|
2067
|
+
```typescript
|
|
2068
|
+
import ForgeSQL, { topSlowestStatementLastHourTrigger } from 'forge-sql-orm';
|
|
2069
|
+
|
|
2070
|
+
// Initialize ForgeSQL ORM instance
|
|
2071
|
+
const forgeSQL = new ForgeSQL();
|
|
2072
|
+
|
|
2073
|
+
// Basic usage with default thresholds (300ms latency, 8MB memory warning)
|
|
2074
|
+
export const memoryUsageTrigger = () =>
|
|
2075
|
+
topSlowestStatementLastHourTrigger(forgeSQL);
|
|
2076
|
+
|
|
2077
|
+
// Conservative memory monitoring: 4MB warning (well below 16MB limit)
|
|
2078
|
+
export const conservativeMemoryTrigger = () =>
|
|
2079
|
+
topSlowestStatementLastHourTrigger(forgeSQL, 300, 4 * 1024 * 1024);
|
|
2080
|
+
|
|
2081
|
+
// Aggressive memory monitoring: 12MB warning (75% of 16MB limit)
|
|
2082
|
+
export const aggressiveMemoryTrigger = () =>
|
|
2083
|
+
topSlowestStatementLastHourTrigger(forgeSQL, 300, 12 * 1024 * 1024);
|
|
2084
|
+
|
|
2085
|
+
// Memory-only monitoring: Only trigger on memory usage (latency effectively disabled)
|
|
2086
|
+
export const memoryOnlyTrigger = () =>
|
|
2087
|
+
topSlowestStatementLastHourTrigger(forgeSQL, 10000, 4 * 1024 * 1024);
|
|
2088
|
+
|
|
2089
|
+
// Latency-only monitoring: Only trigger on slow queries (memory effectively disabled)
|
|
2090
|
+
export const latencyOnlyTrigger = () =>
|
|
2091
|
+
topSlowestStatementLastHourTrigger(forgeSQL, 500, 16 * 1024 * 1024);
|
|
2092
|
+
|
|
2093
|
+
|
|
2094
|
+
#### 3. Configure in manifest.yml
|
|
2095
|
+
|
|
2096
|
+
**As Scheduler Trigger (Recommended for Production):**
|
|
2097
|
+
```yaml
|
|
2098
|
+
scheduledTrigger:
|
|
2099
|
+
- key: memory-usage-trigger
|
|
2100
|
+
function: memoryUsageTrigger
|
|
2101
|
+
interval: hour # Required: only hour interval is supported
|
|
2102
|
+
|
|
2103
|
+
function:
|
|
2104
|
+
- key: memoryUsageTrigger
|
|
2105
|
+
handler: index.memoryUsageTrigger
|
|
2106
|
+
```
|
|
2107
|
+
|
|
2108
|
+
**As Web Trigger (Development Only):**
|
|
2109
|
+
```yaml
|
|
2110
|
+
webtrigger:
|
|
2111
|
+
- key: print-slowest-queries
|
|
2112
|
+
function: memoryUsageTrigger
|
|
2113
|
+
|
|
2114
|
+
function:
|
|
2115
|
+
- key: memoryUsageTrigger
|
|
2116
|
+
handler: index.memoryUsageTrigger
|
|
2117
|
+
```
|
|
2118
|
+
|
|
2119
|
+
> **⚠️ Important**: Web triggers are not recommended for production as they violate the "run-on-atlassian" principle. Use scheduler triggers for production monitoring.
|
|
2120
|
+
|
|
2121
|
+
### How It Works
|
|
2122
|
+
|
|
2123
|
+
The memory monitoring trigger works differently depending on how it's configured:
|
|
2124
|
+
|
|
2125
|
+
#### Scheduler Trigger Mode (Production)
|
|
2126
|
+
|
|
2127
|
+
When used as a **scheduler trigger**, the system:
|
|
2128
|
+
- **Runs automatically** on the configured interval (hour only)
|
|
2129
|
+
- **Logs to Forge Developer Console** only when thresholds are exceeded
|
|
2130
|
+
- **No HTTP response** - operates silently in the background
|
|
2131
|
+
- **Perfect for production** monitoring without violating "run-on-atlassian"
|
|
2132
|
+
|
|
2133
|
+
**Example Console Log Output:**
|
|
2134
|
+
```
|
|
2135
|
+
1. Select avg=3006.03ms max=3006.03ms mem≈0.08MB(max 0.08MB) exec=1
|
|
2136
|
+
digest=28344800f90f6c929484e83337404df7e55a660c5f4ce922c4b298ab5e90c425
|
|
2137
|
+
sql=select `demo_users` . `id` as `a_userid_id` , `demo_users` . `name` as `a_username_name` , `demo_orders` . `product` as `a_product_product` , `demo_orders` . `id` as `a_productid_id` , `sleep` ( ? ) from `demo_users` inner join `demo_orders` on `demo_orders` . `user_id` = `demo_users` . `id`
|
|
2138
|
+
|
|
2139
|
+
full plan:
|
|
2140
|
+
id task estRows operator info actRows execution info memory disk
|
|
2141
|
+
Projection_7 root 2.50 forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.name, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.product, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.id, sleep(?)->Column#7 3 time:3s, loops:2, Concurrency:OFF 1.98 KB N/A
|
|
2142
|
+
└─IndexHashJoin_14 root 2.50 inner join, inner:IndexLookUp_11, outer key:forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, inner key:forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.user_id, equal cond:eq(forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_users.id, forge_38dd1c6156b94bb59c2c9a45582bbfc7.demo_orders.user_id) 3 time:2.11ms, loops:2, inner:{total:1.31ms, concurrency:5, task:1, construct:6.62µs, fetch:1.3ms, build:4.68µs, join:6.14µs} 57.9 KB N/A
|
|
2143
|
+
```
|
|
2144
|
+
|
|
2145
|
+
#### Web Trigger Mode (Development)
|
|
2146
|
+
|
|
2147
|
+
When used as a **web trigger**, the system:
|
|
2148
|
+
- **Runs on-demand** when the web endpoint is called
|
|
2149
|
+
- **Returns JSON response** with detailed metrics
|
|
2150
|
+
- **Logs to console** AND provides structured data
|
|
2151
|
+
- **Useful for development** and debugging
|
|
2152
|
+
|
|
2153
|
+
**Example JSON Response:**
|
|
2154
|
+
```json
|
|
2155
|
+
{
|
|
2156
|
+
"success": true,
|
|
2157
|
+
"window": "last_1h",
|
|
2158
|
+
"top": 1,
|
|
2159
|
+
"warnThresholdMs": 300,
|
|
2160
|
+
"memoryThresholdBytes": 8388608,
|
|
2161
|
+
"rows": [
|
|
2162
|
+
{
|
|
2163
|
+
"rank": 1,
|
|
2164
|
+
"digest": "abc123...",
|
|
2165
|
+
"stmtType": "Select",
|
|
2166
|
+
"schemaName": "myapp",
|
|
2167
|
+
"execCount": 150,
|
|
2168
|
+
"avgLatencyMs": 450.25,
|
|
2169
|
+
"maxLatencyMs": 1200.50,
|
|
2170
|
+
"minLatencyMs": 200.10,
|
|
2171
|
+
"avgProcessTimeMs": 400.20,
|
|
2172
|
+
"avgWaitTimeMs": 50.05,
|
|
2173
|
+
"avgBackoffTimeMs": 0.00,
|
|
2174
|
+
"avgMemMB": 2.5,
|
|
2175
|
+
"maxMemMB": 8.2,
|
|
2176
|
+
"avgMemBytes": 2621440,
|
|
2177
|
+
"maxMemBytes": 8598323,
|
|
2178
|
+
"avgTotalKeys": 1000,
|
|
2179
|
+
"firstSeen": "2024-01-15 10:30:00",
|
|
2180
|
+
"lastSeen": "2024-01-15 11:30:00",
|
|
2181
|
+
"planInCache": true,
|
|
2182
|
+
"planCacheHits": 120,
|
|
2183
|
+
"digestText": "SELECT * FROM users WHERE active = ?",
|
|
2184
|
+
"plan": "IndexScan(users, idx_active)..."
|
|
2185
|
+
}
|
|
2186
|
+
],
|
|
2187
|
+
"generatedAt": "2024-01-15T11:30:00.000Z"
|
|
2188
|
+
}
|
|
2189
|
+
```
|
|
2190
|
+
|
|
2191
|
+
### Configuration Options
|
|
2192
|
+
|
|
2193
|
+
#### Threshold Parameters
|
|
2194
|
+
|
|
2195
|
+
| Parameter | Type | Default | Description |
|
|
2196
|
+
|-----------|------|---------|-------------|
|
|
2197
|
+
| `warnThresholdMs` | `number` | `300` | Latency threshold in milliseconds (secondary) |
|
|
2198
|
+
| `memoryThresholdBytes` | `number` | `8 * 1024 * 1024` | **Memory usage threshold in bytes (primary focus)** |
|
|
2199
|
+
| `options` | `ForgeSqlOrmOptions` | `undefined` | Optional ORM configuration |
|
|
2200
|
+
|
|
2201
|
+
**⚠️ Important: OR Logic**
|
|
2202
|
+
The monitoring uses **OR logic** - if **either** threshold is exceeded, the query will be logged/returned:
|
|
2203
|
+
- Query exceeds `warnThresholdMs` **OR** `memoryThresholdBytes` → Included in results
|
|
2204
|
+
- This means you can set different thresholds for different monitoring priorities
|
|
2205
|
+
- No need to exceed both thresholds simultaneously
|
|
2206
|
+
|
|
2207
|
+
**💡 Pro Tips:**
|
|
2208
|
+
- **Memory-only monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
|
|
2209
|
+
- **Latency-only monitoring**: Set `memoryThresholdBytes` to 16MB (16 * 1024 * 1024) to trigger only on latency
|
|
2210
|
+
- **Combined monitoring**: Use both thresholds for comprehensive monitoring
|
|
2211
|
+
|
|
2212
|
+
**Memory Threshold Guidelines:**
|
|
2213
|
+
- **Conservative**: 4MB (25% of 16MB limit)
|
|
2214
|
+
- **Default**: 8MB (50% of 16MB limit)
|
|
2215
|
+
- **Aggressive**: 12MB (75% of 16MB limit)
|
|
2216
|
+
- **Critical**: 14MB (87.5% of 16MB limit)
|
|
2217
|
+
|
|
2218
|
+
#### Available Intervals
|
|
2219
|
+
|
|
2220
|
+
- `hour` - **Every hour (Required)** - Statistics are available for approximately 12 hours
|
|
2221
|
+
|
|
2222
|
+
> **⚠️ Important**: Due to Forge SQL's statistics retention policy (approximately 12 hours), **only `hour` interval is supported**. Using `day` or `week` intervals will result in incomplete or missing data.
|
|
2018
2223
|
|
|
2019
2224
|
## Migration Guide
|
|
2020
2225
|
|