Skip to content

Commit

Permalink
Merge pull request #4079 from airqo-platform/staging
Browse files Browse the repository at this point in the history
move to production
  • Loading branch information
Baalmart authored Dec 14, 2024
2 parents 8513ca9 + 331742e commit 1f1d50a
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 27 deletions.
2 changes: 1 addition & 1 deletion k8s/analytics/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ images:
celeryWorker: eu.gcr.io/airqo-250220/airqo-analytics-celery-worker
reportJob: eu.gcr.io/airqo-250220/airqo-analytics-report-job
devicesSummaryJob: eu.gcr.io/airqo-250220/airqo-analytics-devices-summary-job
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
api:
name: airqo-analytics-api
label: analytics-api
Expand Down
2 changes: 1 addition & 1 deletion k8s/auth-service/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ app:
replicaCount: 3
image:
repository: eu.gcr.io/airqo-250220/airqo-auth-api
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
nameOverride: ''
fullnameOverride: ''
podAnnotations: {}
Expand Down
2 changes: 1 addition & 1 deletion k8s/auth-service/values-stage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ app:
replicaCount: 2
image:
repository: eu.gcr.io/airqo-250220/airqo-stage-auth-api
tag: stage-4437d7f9-1734102322
tag: stage-ff5c18e5-1734151846
nameOverride: ''
fullnameOverride: ''
podAnnotations: {}
Expand Down
2 changes: 1 addition & 1 deletion k8s/exceedance/values-prod-airqo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ app:
configmap: env-exceedance-production
image:
repository: eu.gcr.io/airqo-250220/airqo-exceedance-job
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
nameOverride: ''
fullnameOverride: ''
2 changes: 1 addition & 1 deletion k8s/exceedance/values-prod-kcca.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ app:
configmap: env-exceedance-production
image:
repository: eu.gcr.io/airqo-250220/kcca-exceedance-job
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
nameOverride: ''
fullnameOverride: ''
2 changes: 1 addition & 1 deletion k8s/predict/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ images:
predictJob: eu.gcr.io/airqo-250220/airqo-predict-job
trainJob: eu.gcr.io/airqo-250220/airqo-train-job
predictPlaces: eu.gcr.io/airqo-250220/airqo-predict-places-air-quality
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
api:
name: airqo-prediction-api
label: prediction-api
Expand Down
2 changes: 1 addition & 1 deletion k8s/spatial/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ app:
replicaCount: 3
image:
repository: eu.gcr.io/airqo-250220/airqo-spatial-api
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
nameOverride: ''
fullnameOverride: ''
podAnnotations: {}
Expand Down
2 changes: 1 addition & 1 deletion k8s/website/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ app:
replicaCount: 3
image:
repository: eu.gcr.io/airqo-250220/airqo-website-api
tag: prod-74ce6c5b-1734102400
tag: prod-8513ca91-1734151901
nameOverride: ''
fullnameOverride: ''
podAnnotations: {}
Expand Down
106 changes: 87 additions & 19 deletions src/auth-service/bin/jobs/preferences-update-job.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const cron = require("node-cron");
const UserModel = require("@models/User");
const mongoose = require("mongoose");
const PreferenceModel = require("@models/Preference");
const SelectedSiteModel = require("@models/SelectedSite");
const constants = require("@config/constants");
Expand All @@ -12,6 +13,30 @@ const stringify = require("@utils/stringify");
const isEmpty = require("is-empty");
const BATCH_SIZE = 100;

// Function to validate critical default values
const validateDefaultValues = () => {
const criticalDefaults = [
{ key: "DEFAULT_GROUP", value: constants.DEFAULT_GROUP },
{ key: "DEFAULT_AIRQLOUD", value: constants.DEFAULT_AIRQLOUD },
{ key: "DEFAULT_GRID", value: constants.DEFAULT_GRID },
{ key: "DEFAULT_NETWORK", value: constants.DEFAULT_NETWORK },
];

const missingDefaults = criticalDefaults.filter(
(item) => isEmpty(item.value) || item.value === undefined
);

if (missingDefaults.length > 0) {
const missingKeys = missingDefaults.map((item) => item.key).join(", ");
logger.error(
`🚨 Aborting preference update: Missing critical default values: ${missingKeys}`
);
return false;
}

return true;
};

// Default preference object
const defaultPreference = {
pollutant: "pm2_5",
Expand All @@ -27,10 +52,22 @@ const defaultPreference = {
unitValue: 14,
unit: "day",
},
airqloud_id: constants.DEFAULT_AIRQLOUD || "NA",
grid_id: constants.DEFAULT_GRID || "NA",
network_id: constants.DEFAULT_NETWORK || "NA",
group_id: constants.DEFAULT_GROUP || "NA",
airqloud_id: constants.DEFAULT_AIRQLOUD,
grid_id: constants.DEFAULT_GRID,
network_id: constants.DEFAULT_NETWORK,
group_id: constants.DEFAULT_GROUP,
};

// Function to validate user's group membership
const validateUserGroupMembership = (user, defaultGroupId) => {
// Check if user has group_roles and is a member of the default group
if (!user.group_roles || user.group_roles.length === 0) {
return false;
}

return user.group_roles.some(
(role) => role.group.toString() === defaultGroupId.toString()
);
};

// Function to get selected sites based on the specified method
Expand Down Expand Up @@ -62,6 +99,11 @@ const getSelectedSites = async (method = "featured") => {
};

const updatePreferences = async (siteSelectionMethod = "featured") => {
// Validate default values before proceeding
if (!validateDefaultValues()) {
return;
}

try {
const batchSize = BATCH_SIZE;
let skip = 0;
Expand All @@ -74,43 +116,60 @@ const updatePreferences = async (siteSelectionMethod = "featured") => {
return;
}

// Use constants.DEFAULT_GROUP directly
const defaultGroupId = mongoose.Types.ObjectId(constants.DEFAULT_GROUP);

while (true) {
// Fetch users with their group_roles
const users = await UserModel("airqo")
.find()
.limit(batchSize)
.skip(skip)
.select("_id")
.select("_id group_roles")
.lean();

if (users.length === 0) {
break;
}

// Fetch existing preferences for users in batch
const userIds = users.map((user) => user._id);
// Filter users who are members of the default group
const validUsers = users.filter((user) =>
validateUserGroupMembership(user, defaultGroupId)
);

// Get user IDs of valid users
const validUserIds = validUsers.map((user) => user._id);

// Fetch existing preferences for valid users
const preferences = await PreferenceModel("airqo")
.find({ user_id: { $in: userIds } })
.find({
user_id: { $in: validUserIds },
group_id: defaultGroupId,
})
.select("_id user_id selected_sites")
.lean();

const preferencesMap = new Map();

preferences.forEach((pref) => {
preferencesMap.set(pref.user_id.toString(), pref);
});

for (const user of users) {
for (const user of validUsers) {
const userIdStr = user._id.toString();
const preference = preferencesMap.get(userIdStr);

// Prepare the default preference object with the specific group_id
const defaultPreferenceWithGroupId = {
...defaultPreference,
user_id: user._id,
group_id: defaultGroupId,
selected_sites: selectedSites,
};

if (!preference) {
// No preference exists, create a new one
// No preference exists for the user in the default group, create a new one
await PreferenceModel("airqo")
.create({
...defaultPreference,
user_id: user._id,
selected_sites: selectedSites,
})
.create(defaultPreferenceWithGroupId)
.catch((error) => {
logger.error(
`🐛🐛 Failed to create preference for user ${userIdStr}: ${stringify(
Expand All @@ -122,14 +181,21 @@ const updatePreferences = async (siteSelectionMethod = "featured") => {
// Preference exists but selected_sites is empty, update it
await PreferenceModel("airqo")
.findOneAndUpdate(
{ _id: preference._id },
{
user_id: user._id,
group_id: defaultGroupId,
},
{
$set: {
...defaultPreference,
selected_sites: selectedSites,
group_id: defaultGroupId,
},
},
{ new: true }
{
new: true,
upsert: true,
setDefaultsOnInsert: true,
}
)
.catch((error) => {
logger.error(
Expand All @@ -154,3 +220,5 @@ cron.schedule(schedule, () => updatePreferences("featured"), {
scheduled: true,
timezone: "Africa/Nairobi",
});

module.exports = { updatePreferences };

0 comments on commit 1f1d50a

Please sign in to comment.