Skip to content

Commit

Permalink
Merge branch 'mongoose' of github.com:austenstone/github-value into m…
Browse files Browse the repository at this point in the history
…ongoose
  • Loading branch information
austenstone committed Jan 21, 2025
2 parents 4dc839e + efef785 commit 1148262
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 54 deletions.
15 changes: 9 additions & 6 deletions backend/src/__tests__/__mock__/survey-gen/mockSurveyGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { addDays } from 'date-fns';
import mongoose from 'mongoose';
import { SurveyMockConfig } from '../types.js';
import SequenceService from '../../../services/sequence.service.js';
import surveyExample from './exampleSurvey.json' assert { type: 'json' };
import { SurveyType } from 'models/survey.model.js';

class MockSurveyGenerator {
private config: SurveyMockConfig;
private baseData: any; // The template data structure
private baseData: any = surveyExample; // The template data structure

constructor(config: SurveyMockConfig, templateData: any) {
this.config = config;
this.baseData = templateData;


}

private getRandomUserId(): string {
Expand Down Expand Up @@ -44,10 +46,11 @@ class MockSurveyGenerator {
return addDays(this.config.startDate, Math.floor(Math.random() * (this.config.endDate.getTime() - this.config.startDate.getTime()) / (1000 * 60 * 60 * 24)));
}

public generateSurveys() {
public async generateSurveys() {
const newData = JSON.parse(JSON.stringify(this.baseData));

newData.surveys = newData.surveys.map((survey: any) => {
newData.surveys = await Promise.all(newData.surveys.map(async (survey: SurveyType) => {
survey.id = await SequenceService.getNextSequenceValue('survey-sequence');
survey.userId = this.getRandomUserId();

Check failure

Code scanning / CodeQL

Insecure randomness High test

This uses a cryptographically insecure random number generated at
Math.random()
in a security context.
survey.org = this.getRandomOrg();
survey.repo = this.getRandomRepo();
Expand All @@ -59,7 +62,7 @@ class MockSurveyGenerator {
survey.createdAt = this.getRandomDate();
survey.updatedAt = this.getRandomDate();
return survey;
});
}));

return newData;
}
Expand Down
19 changes: 9 additions & 10 deletions backend/src/__tests__/__mock__/survey-gen/runSurveyGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,34 @@ const mockConfig: SurveyMockConfig = {
// Load template data from exampleSurvey.json
const templateData: any = surveyExample;

const generateSurveys = () => {
const generateSurveys = async () => {
console.log('Starting to generate surveys...');
try {
const generator = new MockSurveyGenerator(mockConfig, templateData);
const surveys = generator.generateSurveys();
console.log('Successfully generated surveys:', surveys.length);
const surveys = await generator.generateSurveys();
console.log('Successfully generated surveys:', surveys.surveys.length);
return surveys;
} catch (error) {
console.error('Error generating surveys:', error);
throw error; // Re-throw the error after logging it
}
}

const generateSurveysForDate = (datetime: Date) => {
mockConfig.startDate=datetime
mockConfig.endDate=datetime
const generateSurveysForDate = async (datetime: Date) => {
mockConfig.startDate = datetime;
mockConfig.endDate = datetime;
//add other configuration as needed
console.log('Starting to generate surveys...');
try {
const generator = new MockSurveyGenerator(mockConfig, templateData);
const surveys = generator.generateSurveys();
console.log('Successfully generated surveys:', surveys.length);
const surveys = await generator.generateSurveys();
console.log('Successfully generated surveys:', surveys.surveys.length);
return surveys;
} catch (error) {
console.error('Error generating surveys:', error);
throw error; // Re-throw the error after logging it
}
}


// Export function
export { generateSurveys,generateSurveysForDate };
export { generateSurveys, generateSurveysForDate };
135 changes: 108 additions & 27 deletions backend/src/__tests__/services/calendarClockServiceTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import Database from '../../database.js';
import 'dotenv/config';
import seatsExample from '../__mock__/seats-gen/seatsExampleTest.json';

let members: any[] = [];
let membersOas: any[] = []; //octoaustenstone org
let membersOcto: any[] = []; //octodemo org

if (!process.env.MONGODB_URI) throw new Error('MONGODB_URI is not defined');
const database = new Database(process.env.MONGODB_URI);

Expand Down Expand Up @@ -91,7 +93,7 @@ const metricsMockConfig: MockConfig = {
repositories: ['demo/repo1', 'demo/repo2']
};

const seatsMockConfig: SeatsMockConfig = {
const seatsMockConfigOcto: SeatsMockConfig = {
startDate: new Date('2024-11-01'),
endDate: new Date('2024-11-07'),
usagePattern: 'heavy',
Expand All @@ -106,6 +108,21 @@ const metricsMockConfig: MockConfig = {
]
};

const seatsMockConfigOas: SeatsMockConfig = {
startDate: new Date('2024-11-01'),
endDate: new Date('2024-11-07'),
usagePattern: 'heavy',
heavyUsers: ['austenstone', 'mattg57', 'gomtimehta'],
specificUser: 'logan-porelle',
editors: [
'copilot-chat-platform',
'vscode/1.96.2/copilot/1.254.0',
'GitHubGhostPilot/1.0.0/unknown',
'vscode/1.96.2/',
'vscode/1.97.0-insider/copilot-chat/0.24.2024122001'
]
};

function generateMetricsData(datetime: Date) {
metricsMockConfig.startDate=datetime
metricsMockConfig.endDate=datetime
Expand All @@ -116,34 +133,50 @@ function generateMetricsData(datetime: Date) {
return mockGenerator.generateMetrics(metricsMockConfig);
}

function generateSeatsData(datetime: Date, member: any) {
seatsMockConfig.startDate=datetime
seatsMockConfig.endDate=datetime
seatsMockConfig.heavyUsers = [member]
function generateSeatsDataOcto(datetime: Date, member: any) {
seatsMockConfigOcto.startDate=datetime
seatsMockConfigOcto.endDate=datetime
seatsMockConfigOcto.heavyUsers = [member]
//add other configuration as needed
const mockGenerator = new MockSeatsGenerator(seatsMockConfig, { seats: [] });
const mockGenerator = new MockSeatsGenerator(seatsMockConfigOcto, { seats: [] });
return mockGenerator.generateMetrics();
}

function runSurveyGen(datetime: Date) {
function generateSeatsDataOas(datetime: Date, member: any) {
seatsMockConfigOas.startDate=datetime
seatsMockConfigOas.endDate=datetime
seatsMockConfigOas.heavyUsers = [member]
//add other configuration as needed
const mockGenerator = new MockSeatsGenerator(seatsMockConfigOas, { seats: [] });
return mockGenerator.generateMetrics();
}

async function runSurveyGen(datetime: Date) {
if (datetime.getDay() >= 1 && datetime.getDay() <= 5 && datetime.getHours() >= 6 && datetime.getHours() <= 23) {
if (Math.random() < 0.2) {
console.log('Running Survey Generation...', datetime);
const surveys = generateSurveysForDate(datetime);
const surveys = await generateSurveysForDate(datetime);
for (const survey of surveys.surveys) {
SurveyService.createSurvey(survey);
await SurveyService.createSurvey(survey);
}
}
}
}

async function runSeatsGen(datetime: Date) {
console.log('Running Seats Generation...', datetime);
const org = 'octodemo';
//call generateSeatsData for each member of the team by looping through the members array
members.forEach(async (member) => {
const seats = generateSeatsData(datetime, member);
await SeatService.insertSeats(org, datetime, seatsExample.seats);
const orgOcto = 'octodemo';
const orgOas = 'octodemo';
//call generateSeatsData for each member of the org by looping through the members array
membersOas.forEach(async (member) => {
const seats = generateSeatsDataOas(datetime, member);
await SeatService.insertSeats(orgOcto, datetime, seatsExample.seats);
});

//call generateSeatsData for each member of the org by looping through the members array
membersOcto.forEach(async (member) => {
const seats = generateSeatsDataOcto(datetime, member);
await SeatService.insertSeats(orgOas, datetime, seatsExample.seats);
});
}

Expand All @@ -158,10 +191,13 @@ async function runMetricsGen(datetime: Date) {
}

async function calendarClock() {
let datetime = new Date('2024-08-11T00:00:00');
const endDate = new Date('2024-12-09T00:00:00');
members = await TeamsService.getAllMembers('octodemo');
console.log('count All members:', members.length);
let datetime = new Date('2024-11-07T00:00:00');
const endDate = new Date('2025-01-16T00:00:00');
membersOcto = await TeamsService.getAllMembers('octodemo');
membersOas = await TeamsService.getAllMembers('octoaustenstone');
console.log('count Octo members:', membersOcto.length);

console.log('count octoaustenstone members:', membersOas.length);

while (datetime < endDate) {
await runSurveyGen(datetime);
Expand All @@ -175,14 +211,59 @@ async function calendarClock() {
}

async function runClock() {
try {
await database.connect();
await calendarClock();
console.log('All Clock-Triggered Generations worked successfully.');
} catch (error) {
console.error('Test failed:', error);
} finally {
await database.disconnect();
let retryCount = 0;
const maxRetries = 5;
let connected = false;

while (retryCount < maxRetries) {
try {
if (!connected) {
await database.connect();
connected = true;
}

await calendarClock();
console.log('All Clock-Triggered Generations worked successfully.');
break;

} catch (error) {
retryCount++;
console.error(`Attempt ${retryCount}/${maxRetries} failed:`, error.message);

if (error.name === 'MongoServerSelectionError' ||
error.name === 'MongoNetworkError' ||
(error.code && error.code === 10107)) { // Not Primary error code

// Wait with exponential backoff before retrying
const backoffTime = Math.min(1000 * Math.pow(2, retryCount), 30000);
console.log(`Primary failover detected. Waiting ${backoffTime/1000} seconds before retrying...`);
await new Promise(resolve => setTimeout(resolve, backoffTime));

// Force reconnection
try {
await database.disconnect();
connected = false;
} catch (disconnectError) {
console.log('Disconnect error (can be ignored):', disconnectError.message);
}

continue;
}

throw error;
}
}

if (retryCount === maxRetries) {
console.error('Max retries reached. Giving up.');
}

if (connected) {
try {
await database.disconnect();
} catch (disconnectError) {
console.error('Error during final disconnect:', disconnectError.message);
}
}
}
runClock();
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import SeatService from '../../services/copilot.seats.service.js';
import { generateStatefulMetrics } from '../__mock__/seats-gen/runSeatsGenerator.js';
import Database from '../../database.js';
import 'dotenv/config';
import { SeatType } from 'models/copilot.seats.model.js';

if (!process.env.MONGODB_URI) throw new Error('MONGODB_URI is not defined');
const database = new Database(process.env.MONGODB_URI);
Expand All @@ -14,7 +15,7 @@ async function runTest() {
// Test data setup
const org = 'octodemo';
const queryAt = new Date();
const seats = generateStatefulMetrics();
const seats = generateStatefulMetrics();


//loop through each seat and if the last_activity_at is "false" print the seat object to console.
Expand Down
6 changes: 4 additions & 2 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class App {
) {
this.baseUrl = process.env.BASE_URL || 'http://localhost:' + port;
this.e = express();
this.port = port;
this.port = Number(process.env.PORT); //bugfix?
logger.info('port number found');
if (!process.env.MONGODB_URI) {
throw new Error('MONGODB_URI must be set');
}
Expand Down Expand Up @@ -122,7 +123,8 @@ class App {
(_, res) => res.sendFile(path.join(frontendPath, 'index.html'))
);

this.eListener = this.e.listen(this.port);
this.eListener = this.e.listen(this.port, '0.0.0.0');

}

private initializeSettings() {
Expand Down
6 changes: 5 additions & 1 deletion backend/src/controllers/survey.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ class SurveyController {
try {
const { id } = req.params;
const Survey = mongoose.model('Survey');
const survey = await Survey.findOne({ id: id })
const survey = await Survey.findOne({ id: Number(id) }); // Cast `id` to Number
if (!survey) {
res.status(404).json({ message: 'Survey not found' });
return;
}
res.status(200).json(survey);
} catch (error) {
res.status(500).json(error);
Expand Down
26 changes: 19 additions & 7 deletions backend/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,29 @@ class Database {
}

async connect() {
//improve the logger message @12:12

logger.info('Connecting to the database', this.mongodbUri);
if (this.mongodbUri) await updateDotenv({ MONGODB_URI: this.mongodbUri });
try {
this.mongoose = await mongoose.connect(this.mongodbUri, {
//useNewUrlParser: true,
//useUnifiedTopology: true,
socketTimeoutMS: 60000, // Set the socket timeout (e.g., 60 seconds)
connectTimeoutMS: 30000, // Connection timeout (e.g., 30 seconds)
serverSelectionTimeoutMS: 30000, // Server selection timeout
socketTimeoutMS: 90000,
connectTimeoutMS: 60000,
serverSelectionTimeoutMS: 30000,
retryWrites: true,
readPreference: 'primaryPreferred',
retryReads: true,
w: 'majority',
// Add these connection pool settings
maxPoolSize: 10, // Limit maximum connections
minPoolSize: 5, // Keep minimum connections ready
maxIdleTimeMS: 30000, // Close idle connections after 30 seconds
heartbeatFrequencyMS: 10000, // Check connection status every 10 seconds
// Add buffer commands setting
bufferCommands: true, // Queue operations when connection is lost
// Add connection pool monitoring
monitorCommands: true
});
// this.mongoose.set('debug', false);
mongoose.set('debug', (collectionName: string, methodName: string, ...methodArgs: unknown[]) => {
const msgMapper = (m: unknown) => {
return util.inspect(m, false, 10, true)
Expand Down Expand Up @@ -286,7 +298,7 @@ class Database {
timestamps: true
}));
}

async disconnect() {
await this.mongoose?.disconnect();
}
Expand Down
6 changes: 6 additions & 0 deletions backend/src/models/counter.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type CounterType = {
_id: string; // Ensure _id is of type string
seq: number;
}

export default CounterType;
Loading

0 comments on commit 1148262

Please sign in to comment.