Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 105 additions & 10 deletions pet-nutrition-service/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,142 @@
const logger = require('pino-http');
const NutritionFact = require('./nutrition-fact')

main().catch(err => console.log(err));
let isConnected = false;

async function main () {
// MongoDB connection with retry logic
async function connectWithRetry() {
const maxRetries = 5;
const retryDelay = 1000; // Start with 1 second

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const MONGO_URI = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/nutrition';
await mongoose.connect(MONGO_URI, {
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
});
isConnected = true;
console.log('MongoDB connected successfully');
return;
} catch (error) {
console.error(`MongoDB connection attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw error;
}
// Exponential backoff
await new Promise(resolve => setTimeout(resolve, retryDelay * Math.pow(2, attempt - 1)));
}
}
}

main().catch(err => {
console.error('Application startup failed:', err);
process.exit(1);
});

async function main() {
const app = express();

// Middlware
// Middleware
app.use(logger());
app.use(express.json());

// Health check endpoint
app.get('/health', (req, res) => {
const status = isConnected ? 'healthy' : 'unhealthy';
const statusCode = isConnected ? 200 : 503;
res.status(statusCode).json({
status,
database: isConnected ? 'connected' : 'disconnected',
timestamp: new Date().toISOString()
});
});

// GET: Find a NutritionFact by pet_type
app.get('/nutrition/:pet_type', async (req, res) => {
try {
if (!isConnected) {
return res.status(503).json({
message: 'Database connection unavailable',
error: 'SERVICE_UNAVAILABLE'
});
}

const { pet_type } = req.params;
const fact = await NutritionFact.findOne({ pet_type });

// Input validation
if (!pet_type || pet_type.trim() === '') {
return res.status(400).json({
message: 'Pet type is required',
error: 'INVALID_INPUT'
});
}

const fact = await NutritionFact.findOne({ pet_type: pet_type.toLowerCase() });
if (!fact) {
return res.status(404).json({ message: 'nutrition fact not found for the given pet_type' });
return res.status(404).json({
message: `No nutrition information found for pet type: ${pet_type}`,
error: 'NOT_FOUND',
pet_type
});
}
res.status(200).json(fact);
} catch (error) {
req.log.error(error);
res.status(500).json({ message: 'failed to fetch nutrition fact', error });
res.status(500).json({
message: 'Failed to fetch nutrition information',
error: 'DATABASE_ERROR',
details: error.message
});
}
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

// GET: Fetch all NutritionFacts
app.get('/nutrition', async (req, res) => {
try {
if (!isConnected) {
return res.status(503).json({
message: 'Database connection unavailable',
error: 'SERVICE_UNAVAILABLE'
});
}

const facts = await NutritionFact.find();
res.status(200).json(facts);
} catch (error) {
res.status(500).json({ message: 'Failed to fetch nutrition facts', error });
req.log.error(error);
res.status(500).json({
message: 'Failed to fetch nutrition facts',
error: 'DATABASE_ERROR',
details: error.message
});
}
});

const MONGO_URI = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/'
await mongoose.connect(MONGO_URI);
// MongoDB connection monitoring
mongoose.connection.on('connected', () => {
isConnected = true;
console.log('MongoDB connection established');
});

mongoose.connection.on('error', (err) => {
isConnected = false;
console.error('MongoDB connection error:', err);
});

mongoose.connection.on('disconnected', () => {
isConnected = false;
console.log('MongoDB disconnected');
});

// Connect to MongoDB with retry logic
await connectWithRetry();

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
require('./eureka-client')('nutrition-service', PORT);
require('./db-seed')();
console.log(`server running on port ${PORT}`);
console.log(`Server running on port ${PORT}`);
});
}