ensure-mongo-fcv.ts 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Ensures MongoDB Feature Compatibility Version matches the mongo image (8.2).
  2. // Required when the mongo image is upgraded while existing data persists in the volume.
  3. // https://www.mongodb.com/ja-jp/docs/upcoming/release-notes/8.2-upgrade-standalone/
  4. //
  5. // Run with Node's native TypeScript support (>= v22.6 with strip-types,
  6. // enabled by default in v24+). Resolution base is pinned to apps/app/ so the
  7. // mongodb driver installed there can be loaded without changing cwd.
  8. import { createRequire } from 'node:module';
  9. const require = createRequire('/workspace/growi/apps/app/');
  10. const { MongoClient } = require('mongodb') as typeof import('mongodb');
  11. const URI = 'mongodb://mongo:27017';
  12. const TARGET_FCV = '8.2';
  13. const MAX_RETRIES = 30;
  14. const RETRY_INTERVAL_MS = 2000;
  15. const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));
  16. async function waitForMongo(): Promise<void> {
  17. for (let i = 0; i < MAX_RETRIES; i++) {
  18. const client = new MongoClient(URI, { serverSelectionTimeoutMS: 2000 });
  19. try {
  20. await client.connect();
  21. await client.db('admin').command({ ping: 1 });
  22. return;
  23. }
  24. catch {
  25. await sleep(RETRY_INTERVAL_MS);
  26. }
  27. finally {
  28. await client.close().catch(() => {});
  29. }
  30. }
  31. throw new Error(`MongoDB at ${URI} did not become ready in time`);
  32. }
  33. async function ensureFcv(): Promise<void> {
  34. const client = new MongoClient(URI);
  35. await client.connect();
  36. try {
  37. const admin = client.db('admin');
  38. const result = await admin.command({
  39. getParameter: 1,
  40. featureCompatibilityVersion: 1,
  41. }) as { featureCompatibilityVersion: { version: string } };
  42. const version = result.featureCompatibilityVersion.version;
  43. if (version === TARGET_FCV) {
  44. console.log(`FCV already ${TARGET_FCV}`);
  45. return;
  46. }
  47. await admin.command({ setFeatureCompatibilityVersion: TARGET_FCV, confirm: true });
  48. console.log(`FCV upgraded: ${version} -> ${TARGET_FCV}`);
  49. }
  50. finally {
  51. await client.close();
  52. }
  53. }
  54. console.log('Waiting for MongoDB to be ready...');
  55. await waitForMongo();
  56. console.log(`Ensuring MongoDB featureCompatibilityVersion is ${TARGET_FCV}...`);
  57. try {
  58. await ensureFcv();
  59. }
  60. catch (e) {
  61. console.error('FCV upgrade failed:', (e as Error).message);
  62. }