1+ #!/usr/bin/env node
2+ import 'dotenv/config' ;
3+ import pg from 'pg' ;
4+ import { createClient } from 'redis' ;
5+
6+ const { Client } = pg ;
7+
8+ // Railway PostgreSQL URL from environment
9+ const DATABASE_URL = process . env . DATABASE_URL ||
10+ 'postgresql://postgres:YTSFXqPzFhghOcefgwPvJyWOBTYHbYxd@postgres.railway.internal:5432/railway' ;
11+
12+ async function testPostgreSQL ( ) {
13+ console . log ( '🐘 Testing PostgreSQL Connection...\n' ) ;
14+
15+ const pgClient = new Client ( {
16+ connectionString : DATABASE_URL
17+ } ) ;
18+
19+ try {
20+ console . log ( '📡 Connecting to PostgreSQL...' ) ;
21+ await pgClient . connect ( ) ;
22+ console . log ( '✅ Connected to PostgreSQL!\n' ) ;
23+
24+ // Test basic query
25+ const timeResult = await pgClient . query ( 'SELECT NOW() as current_time' ) ;
26+ console . log ( '⏰ Database time:' , timeResult . rows [ 0 ] . current_time ) ;
27+
28+ // Create frames table if it doesn't exist
29+ console . log ( '\n📊 Creating frames table...' ) ;
30+ await pgClient . query ( `
31+ CREATE TABLE IF NOT EXISTS frames (
32+ frame_id TEXT PRIMARY KEY,
33+ run_id TEXT NOT NULL,
34+ project_id TEXT NOT NULL,
35+ parent_frame_id TEXT,
36+ depth INTEGER DEFAULT 0,
37+ type TEXT NOT NULL,
38+ name TEXT NOT NULL,
39+ state TEXT DEFAULT 'active',
40+ inputs JSONB DEFAULT '{}',
41+ outputs JSONB DEFAULT '{}',
42+ digest_text TEXT,
43+ digest_json JSONB DEFAULT '{}',
44+ created_at TIMESTAMP DEFAULT NOW(),
45+ closed_at TIMESTAMP
46+ );
47+
48+ CREATE INDEX IF NOT EXISTS idx_frames_project ON frames(project_id);
49+ CREATE INDEX IF NOT EXISTS idx_frames_state ON frames(state);
50+ CREATE INDEX IF NOT EXISTS idx_frames_created ON frames(created_at);
51+ ` ) ;
52+ console . log ( '✅ Frames table ready!\n' ) ;
53+
54+ // Check existing frames
55+ const countResult = await pgClient . query ( 'SELECT COUNT(*) as count FROM frames' ) ;
56+ console . log ( '📈 Existing frames:' , countResult . rows [ 0 ] . count ) ;
57+
58+ // Insert a test frame
59+ const testFrameId = `test-frame-${ Date . now ( ) } ` ;
60+ console . log ( '\n🔧 Inserting test frame...' ) ;
61+ await pgClient . query ( `
62+ INSERT INTO frames (
63+ frame_id, run_id, project_id, type, name, state,
64+ inputs, outputs, digest_text
65+ ) VALUES (
66+ $1, $2, $3, $4, $5, $6, $7, $8, $9
67+ )
68+ ` , [
69+ testFrameId ,
70+ 'test-run-001' ,
71+ 'stackmemory-test' ,
72+ 'test' ,
73+ 'Database Connection Test' ,
74+ 'active' ,
75+ JSON . stringify ( { test : true , timestamp : new Date ( ) . toISOString ( ) } ) ,
76+ JSON . stringify ( { success : true } ) ,
77+ 'Test frame for Railway PostgreSQL connection'
78+ ] ) ;
79+ console . log ( '✅ Test frame inserted:' , testFrameId ) ;
80+
81+ // Retrieve the test frame
82+ console . log ( '\n🔍 Retrieving test frame...' ) ;
83+ const frameResult = await pgClient . query (
84+ 'SELECT * FROM frames WHERE frame_id = $1' ,
85+ [ testFrameId ]
86+ ) ;
87+
88+ if ( frameResult . rows . length > 0 ) {
89+ const frame = frameResult . rows [ 0 ] ;
90+ console . log ( '✅ Frame retrieved successfully!' ) ;
91+ console . log ( ' - Name:' , frame . name ) ;
92+ console . log ( ' - Type:' , frame . type ) ;
93+ console . log ( ' - State:' , frame . state ) ;
94+ console . log ( ' - Created:' , frame . created_at ) ;
95+ }
96+
97+ // Get recent frames
98+ console . log ( '\n📋 Recent frames:' ) ;
99+ const recentFrames = await pgClient . query ( `
100+ SELECT frame_id, name, type, state, created_at
101+ FROM frames
102+ ORDER BY created_at DESC
103+ LIMIT 5
104+ ` ) ;
105+
106+ if ( recentFrames . rows . length > 0 ) {
107+ recentFrames . rows . forEach ( ( frame , index ) => {
108+ console . log ( ` ${ index + 1 } . ${ frame . name } (${ frame . type } ) - ${ frame . state } ` ) ;
109+ } ) ;
110+ } else {
111+ console . log ( ' No frames found' ) ;
112+ }
113+
114+ // Check table information
115+ console . log ( '\n📊 Database tables:' ) ;
116+ const tables = await pgClient . query ( `
117+ SELECT table_name
118+ FROM information_schema.tables
119+ WHERE table_schema = 'public'
120+ ORDER BY table_name
121+ ` ) ;
122+
123+ tables . rows . forEach ( row => {
124+ console . log ( ` - ${ row . table_name } ` ) ;
125+ } ) ;
126+
127+ } catch ( error ) {
128+ console . error ( '❌ PostgreSQL Error:' , error . message ) ;
129+ if ( error . message . includes ( 'ENOTFOUND' ) ) {
130+ console . log ( '\n💡 Note: postgres.railway.internal only works from within Railway' ) ;
131+ console . log ( ' For local testing, you need the external DATABASE_URL' ) ;
132+ }
133+ } finally {
134+ await pgClient . end ( ) ;
135+ console . log ( '\n🔌 PostgreSQL connection closed' ) ;
136+ }
137+ }
138+
139+ async function testRedis ( ) {
140+ console . log ( '\n\n🔴 Testing Redis Connection...\n' ) ;
141+
142+ // Try to build Redis URL from environment
143+ const REDIS_URL = process . env . REDIS_URL ||
144+ process . env . REDISHOST ? `redis://${ process . env . REDISHOST } :${ process . env . REDISPORT || 6379 } ` : null ;
145+
146+ if ( ! REDIS_URL ) {
147+ console . log ( '⚠️ No Redis configuration found in environment' ) ;
148+ console . log ( ' Add REDIS_URL or REDISHOST to Railway variables' ) ;
149+ return ;
150+ }
151+
152+ const redisClient = createClient ( { url : REDIS_URL } ) ;
153+
154+ try {
155+ console . log ( '📡 Connecting to Redis...' ) ;
156+ await redisClient . connect ( ) ;
157+ console . log ( '✅ Connected to Redis!\n' ) ;
158+
159+ // Test basic operations
160+ console . log ( '🔧 Testing Redis operations...' ) ;
161+
162+ // Set a test key
163+ const testKey = `test:connection:${ Date . now ( ) } ` ;
164+ await redisClient . set ( testKey , JSON . stringify ( {
165+ test : true ,
166+ timestamp : new Date ( ) . toISOString ( ) ,
167+ message : 'Railway Redis connection test'
168+ } ) , { EX : 60 } ) ; // Expire after 60 seconds
169+ console . log ( '✅ Set test key:' , testKey ) ;
170+
171+ // Get the test key
172+ const value = await redisClient . get ( testKey ) ;
173+ const parsed = JSON . parse ( value ) ;
174+ console . log ( '✅ Retrieved value:' , parsed ) ;
175+
176+ // Test Redis info
177+ const info = await redisClient . info ( 'server' ) ;
178+ const version = info . match ( / r e d i s _ v e r s i o n : ( .+ ) / ) ?. [ 1 ] ;
179+ console . log ( '\n📊 Redis Server Info:' ) ;
180+ console . log ( ' - Version:' , version ) ;
181+
182+ // Check memory usage
183+ const memoryInfo = await redisClient . info ( 'memory' ) ;
184+ const usedMemory = memoryInfo . match ( / u s e d _ m e m o r y _ h u m a n : ( .+ ) / ) ?. [ 1 ] ;
185+ console . log ( ' - Memory used:' , usedMemory ) ;
186+
187+ // List all keys (be careful in production!)
188+ const keys = await redisClient . keys ( '*' ) ;
189+ console . log ( ' - Total keys:' , keys . length ) ;
190+
191+ if ( keys . length > 0 && keys . length <= 10 ) {
192+ console . log ( ' - Keys:' , keys ) ;
193+ }
194+
195+ } catch ( error ) {
196+ console . error ( '❌ Redis Error:' , error . message ) ;
197+ if ( error . message . includes ( 'ENOTFOUND' ) ) {
198+ console . log ( '\n💡 Note: Redis host not found' ) ;
199+ console . log ( ' Make sure Redis variables are configured in Railway' ) ;
200+ }
201+ } finally {
202+ await redisClient . disconnect ( ) ;
203+ console . log ( '\n🔌 Redis connection closed' ) ;
204+ }
205+ }
206+
207+ // Run tests
208+ async function runTests ( ) {
209+ console . log ( '🚀 Railway Database Connection Tests\n' ) ;
210+ console . log ( '=' . repeat ( 50 ) ) ;
211+
212+ await testPostgreSQL ( ) ;
213+ await testRedis ( ) ;
214+
215+ console . log ( '\n' + '=' . repeat ( 50 ) ) ;
216+ console . log ( '✅ Tests complete!\n' ) ;
217+ }
218+
219+ runTests ( ) . catch ( error => {
220+ console . error ( 'Fatal error:' , error ) ;
221+ process . exit ( 1 ) ;
222+ } ) ;
0 commit comments