Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#217 rework runtine #286

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,14 @@ COPY web/nginx.conf web/
# to build only back run
# docker build . --target api --tag my-api-tag`
FROM node:20-alpine as api
RUN npm install -g forever@4.0.3
RUN apk add --no-cache \
git \
openssh-client \
ca-certificates
COPY --from=build /app/api/dist/index.js .
# For reading the version number
COPY --from=build /app/package.json .
ENTRYPOINT sh -c "forever index.js"
ENTRYPOINT sh -c "node index.js"



Expand Down
24 changes: 0 additions & 24 deletions api/Dockerfile

This file was deleted.

11 changes: 7 additions & 4 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@
"test": "vitest --watch=false --no-file-parallelism",
"dev": "yarn build && yarn start",
"build": "tsc",
"start": "yarn db:up && dotenv -e ../.env -- forever dist/src/main.js",
"start": "yarn db:up && dotenv -e ../.env -- node dist/src/main.js",
"update": "dotenv -e ../.env -- node dist/src/update.js",
"import": "dotenv -e ../.env -- node dist/src/import.js",
"build-prod": "esbuild src/main.ts --bundle --platform=node --target=node20 --outfile=dist/index.js",
"start-prod": "yarn db:up && dotenv -e ../.env -- forever dist/index.js",
"start-prod": "yarn db:up && dotenv -e ../.env -- node dist/index.js",
"_format": "prettier \"**/*.{ts,tsx,json,md}\"",
"format": "yarn run _format --write",
"format:check": "yarn run _format --list-different",
"link-in-web": "ts-node --skipProject scripts/link-in-app.ts sill-web",
"reset-data-test": "ts-node --skipProject scripts/reset-data-test.ts",
"compile-data": "./.env.local.sh ts-node --skipProject scripts/compile-data.ts",
"load-git-repo-in-pg": "dotenv -e ../.env -- node --loader ts-node/esm --experimental-specifier-resolution=node scripts/load-git-repo-in-pg.ts",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"dev:db": "docker compose -f ../docker-compose.resources.yml up -d",
"dev:reset": "docker stop sill-postgres-1 && docker rm sill-postgres-1 && docker compose -f ../docker-compose.resources.yml up -d"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ici tu peux aussi faire :

Suggested change
"dev:reset": "docker stop sill-postgres-1 && docker rm sill-postgres-1 && docker compose -f ../docker-compose.resources.yml up -d"
"dev:reset": "docker compose -f ../docker-compose.resources.yml down && rm -rf docker-data && docker compose -f ../docker-compose.resources.yml up -d"

},
"author": "DINUM",
"license": "MIT",
Expand Down Expand Up @@ -58,7 +62,6 @@
"esbuild": "^0.23.0",
"evt": "^2.5.7",
"express": "^4.17.2",
"forever": "^4.0.3",
"i18nifty": "^3.2.0",
"memoizee": "^0.4.15",
"node-fetch": "^2.6.7",
Expand Down
6 changes: 1 addition & 5 deletions api/scripts/compile-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import { env } from "../src/env";
"kyselyDb": kyselyDb
},
"githubPersonalAccessTokenForApiRateLimit": env.githubPersonalAccessTokenForApiRateLimit,
"doPerPerformPeriodicalCompilation": false,
"doPerformCacheInitialization": false,
"externalSoftwareDataOrigin": env.externalSoftwareDataOrigin,
"initializeSoftwareFromSource": env.initializeSoftwareFromSource,
"botAgentEmail": env.botAgentEmail
"externalSoftwareDataOrigin": env.externalSoftwareDataOrigin
});

await useCases.fetchAndSaveExternalDataForAllSoftwares();
Expand Down
5 changes: 0 additions & 5 deletions api/src/core/adapters/fetchExternalData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,11 +524,6 @@ describe("fetches software extra data (from different providers)", () => {
cdlUrl: "https://comptoir-du-libre.org/fr/users/3216",
website: "https://cap-rel.fr"
},
{
name: "YPOK",
siren: "434940763",
cnllUrl: "https://annuaire.cnll.fr/societes/434940763"
},
{
name: "Entr'ouvert",
siren: "443170139",
Expand Down
58 changes: 1 addition & 57 deletions api/src/core/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import type { GetSoftwareLatestVersion } from "./ports/GetSoftwareLatestVersion"
import { UseCases } from "./usecases";
import { makeGetAgent } from "./usecases/getAgent";
import { makeGetSoftwareFormAutoFillDataFromExternalAndOtherSources } from "./usecases/getSoftwareFormAutoFillDataFromExternalAndOtherSources";
import { importFromHALSource, importFromWikidataSource } from "./usecases/importFromSource";

type PgDbConfig = { dbKind: "kysely"; kyselyDb: Kysely<Database> };

Expand All @@ -26,12 +25,7 @@ type DbConfig = PgDbConfig;
type ParamsOfBootstrapCore = {
dbConfig: DbConfig;
githubPersonalAccessTokenForApiRateLimit: string;
doPerPerformPeriodicalCompilation: boolean;
doPerformCacheInitialization: boolean;
externalSoftwareDataOrigin: ExternalDataOrigin;
initializeSoftwareFromSource: boolean;
botAgentEmail: string | undefined;
listToImport?: string[];
};

export type Context = {
Expand All @@ -56,15 +50,7 @@ const getDbApiAndInitializeCache = (dbConfig: DbConfig): { dbApi: DbApiV2 } => {
export async function bootstrapCore(
params: ParamsOfBootstrapCore
): Promise<{ dbApi: DbApiV2; context: Context; useCases: UseCases }> {
const {
dbConfig,
githubPersonalAccessTokenForApiRateLimit,
doPerPerformPeriodicalCompilation,
externalSoftwareDataOrigin,
initializeSoftwareFromSource,
botAgentEmail,
listToImport
} = params;
const { dbConfig, githubPersonalAccessTokenForApiRateLimit, externalSoftwareDataOrigin } = params;

const { getSoftwareLatestVersion } = createGetSoftwareLatestVersion({
githubPersonalAccessTokenForApiRateLimit
Expand Down Expand Up @@ -96,48 +82,6 @@ export async function bootstrapCore(
getAgent: makeGetAgent({ agentRepository: dbApi.agent })
};

if (initializeSoftwareFromSource) {
if (!botAgentEmail) throw new Error("No bot agent email provided");
if (externalSoftwareDataOrigin === "HAL") {
console.info(" ------ Feeding database with HAL software started ------");
const importHAL = importFromHALSource(dbApi);
try {
await importHAL(botAgentEmail);
} catch (err) {
// catches errors both in fetch and response.json
console.error(err);
}

console.info(" ------ Feeding database with HAL software finished ------");
}
if (externalSoftwareDataOrigin === "wikidata") {
console.info(" ------ Feeding database with Wikidata software started ------");
const importWikidata = importFromWikidataSource(dbApi);
try {
await importWikidata(botAgentEmail, listToImport ?? []);
} catch (err) {
console.error(err);
}
console.info(" ------ Feeding database with Wikidata software finished ------");
}
}

if (doPerPerformPeriodicalCompilation) {
const frequencyOfUpdate = 1000 * 60 * 60 * 4; // 4 hours

const updateSoftwareExternalData = async () => {
console.info("------ Updating software external data started ------");
await useCases.fetchAndSaveExternalDataForAllSoftwares();
console.info("------ Updating software external data finished ------");
setTimeout(async () => {
await updateSoftwareExternalData();
}, frequencyOfUpdate);
};

// start the periodical compilation 15 secondes after api starts
void setTimeout(() => updateSoftwareExternalData(), 1000 * 15);
}

return { dbApi, context, useCases };
}

Expand Down
57 changes: 57 additions & 0 deletions api/src/core/importTool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Kysely } from "kysely";
import { createKyselyPgDbApi } from "./adapters/dbApi/kysely/createPgDbApi";
import { Database } from "./adapters/dbApi/kysely/kysely.database";
import { DbApiV2 } from "./ports/DbApiV2";
import type { ExternalDataOrigin } from "./ports/GetSoftwareExternalData";
import { importFromHALSource, importFromWikidataSource } from "./usecases/importFromSource";

type PgDbConfig = { dbKind: "kysely"; kyselyDb: Kysely<Database> };

type DbConfig = PgDbConfig;

type ParamsOfImportTool = {
dbConfig: DbConfig;
externalSoftwareDataOrigin: ExternalDataOrigin;
botAgentEmail: string | undefined;
listToImport?: string[];
};

const getDbApiAndInitializeCache = (dbConfig: DbConfig): { dbApi: DbApiV2 } => {
if (dbConfig.dbKind === "kysely") {
return {
dbApi: createKyselyPgDbApi(dbConfig.kyselyDb)
};
}

const shouldNotBeReached: never = dbConfig.dbKind;
throw new Error(`Unsupported case: ${shouldNotBeReached}`);
};

export async function importTool(params: ParamsOfImportTool): Promise<boolean> {
const { dbConfig, externalSoftwareDataOrigin, botAgentEmail, listToImport } = params;

const { dbApi } = getDbApiAndInitializeCache(dbConfig);

if (!botAgentEmail) throw new Error("No bot agent email provided");
if (externalSoftwareDataOrigin === "HAL") {
console.info(" ------ Feeding database with HAL software started ------");
const importHAL = importFromHALSource(dbApi);
return importHAL(botAgentEmail).then(promises =>
Promise.all(promises).then(() => {
console.info(" ------ Feeding database with HAL software finished ------");
return true;
})
);
} else if (externalSoftwareDataOrigin === "wikidata") {
console.info(" ------ Feeding database with Wikidata software started ------");
const importWikidata = importFromWikidataSource(dbApi);
return importWikidata(botAgentEmail, listToImport ?? []).then(promises =>
Promise.all(promises).then(() => {
console.info(" ------ Feeding database with Wikidata software finished ------");
return true;
})
);
} else {
return Promise.reject(`${externalSoftwareDataOrigin} not supported`);
}
}
82 changes: 82 additions & 0 deletions api/src/core/updateTools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Kysely } from "kysely";
import { comptoirDuLibreApi } from "./adapters/comptoirDuLibreApi";
import { createKyselyPgDbApi } from "./adapters/dbApi/kysely/createPgDbApi";
import { Database } from "./adapters/dbApi/kysely/kysely.database";
import { makeFetchAndSaveExternalDataForAllSoftwares } from "./adapters/fetchExternalData";
import { getCnllPrestatairesSill } from "./adapters/getCnllPrestatairesSill";
import { getServiceProviders } from "./adapters/getServiceProviders";
import { createGetSoftwareLatestVersion } from "./adapters/getSoftwareLatestVersion";
import { getWikidataSoftware } from "./adapters/wikidata/getWikidataSoftware";
import { getWikidataSoftwareOptions } from "./adapters/wikidata/getWikidataSoftwareOptions";
import { halAdapter } from "./adapters/hal";
import { DbApiV2 } from "./ports/DbApiV2";
import type { ExternalDataOrigin, GetSoftwareExternalData } from "./ports/GetSoftwareExternalData";
import type { GetSoftwareExternalDataOptions } from "./ports/GetSoftwareExternalDataOptions";

type PgDbConfig = { dbKind: "kysely"; kyselyDb: Kysely<Database> };

type DbConfig = PgDbConfig;

type ParamsOfUpdateService = {
dbConfig: DbConfig;
githubPersonalAccessTokenForApiRateLimit: string;
externalSoftwareDataOrigin: ExternalDataOrigin;
};

const getDbApiAndInitializeCache = (dbConfig: DbConfig): { dbApi: DbApiV2 } => {
if (dbConfig.dbKind === "kysely") {
return {
dbApi: createKyselyPgDbApi(dbConfig.kyselyDb)
};
}

const shouldNotBeReached: never = dbConfig.dbKind;
throw new Error(`Unsupported case: ${shouldNotBeReached}`);
};

export async function updateTool(params: ParamsOfUpdateService): Promise<boolean> {
const { dbConfig, githubPersonalAccessTokenForApiRateLimit, externalSoftwareDataOrigin } = params;

const { getSoftwareLatestVersion } = createGetSoftwareLatestVersion({
githubPersonalAccessTokenForApiRateLimit
});

const { getSoftwareExternalData } = getSoftwareExternalDataFunctions(externalSoftwareDataOrigin);

const { dbApi } = getDbApiAndInitializeCache(dbConfig);

const fetchAndSaveExternalDataForAllSoftwares = makeFetchAndSaveExternalDataForAllSoftwares({
getSoftwareExternalData,
getCnllPrestatairesSill,
comptoirDuLibreApi,
getSoftwareLatestVersion,
getServiceProviders,
dbApi
});
console.info("------ Updating software external data started ------");
await fetchAndSaveExternalDataForAllSoftwares();
console.info("------ Updating software external data finished ------");

return Promise.resolve(true);
}

function getSoftwareExternalDataFunctions(externalSoftwareDataOrigin: ExternalDataOrigin): {
"getSoftwareExternalDataOptions": GetSoftwareExternalDataOptions;
"getSoftwareExternalData": GetSoftwareExternalData;
} {
switch (externalSoftwareDataOrigin) {
case "wikidata":
return {
"getSoftwareExternalDataOptions": getWikidataSoftwareOptions,
"getSoftwareExternalData": getWikidataSoftware
};
case "HAL":
return {
"getSoftwareExternalDataOptions": halAdapter.softwareOptions.getByHalId,
"getSoftwareExternalData": halAdapter.softwareExternalData.getByHalId
};
default:
const unreachableCase: never = externalSoftwareDataOrigin;
throw new Error(`Unreachable case: ${unreachableCase}`);
}
}
4 changes: 4 additions & 0 deletions api/src/import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { env } from "./env";
import { startImportService } from "./rpc/import";

startImportService(env).then(() => console.log("Closing import"));
6 changes: 1 addition & 5 deletions api/src/rpc/createTestCaller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ export const createTestCaller = async ({ user }: TestCallerConfig = { user: defa
const { dbApi, useCases } = await bootstrapCore({
"dbConfig": { dbKind: "kysely", kyselyDb },
"githubPersonalAccessTokenForApiRateLimit": "fake-token",
"doPerPerformPeriodicalCompilation": false,
"doPerformCacheInitialization": false,
"externalSoftwareDataOrigin": externalSoftwareDataOrigin,
"botAgentEmail": "bot@mydomain.fr",
"initializeSoftwareFromSource": false
"externalSoftwareDataOrigin": externalSoftwareDataOrigin
});

const { router } = createRouter({
Expand Down
44 changes: 44 additions & 0 deletions api/src/rpc/import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Kysely } from "kysely";
import type { Equals } from "tsafe";
import { assert } from "tsafe/assert";
import { Database } from "../core/adapters/dbApi/kysely/kysely.database";
import { createPgDialect } from "../core/adapters/dbApi/kysely/kysely.dialect";
import type { ExternalDataOrigin } from "../core/ports/GetSoftwareExternalData";
import { importTool } from "../core/importTool";

export async function startImportService(params: {
isDevEnvironnement: boolean;
externalSoftwareDataOrigin: ExternalDataOrigin;
databaseUrl: string;
botAgentEmail?: string;
initializeSoftwareFromSource: boolean;
listToImport?: string[];
}) {
const {
isDevEnvironnement,
externalSoftwareDataOrigin,
databaseUrl,
initializeSoftwareFromSource,
botAgentEmail,
listToImport,
...rest
} = params;

assert<Equals<typeof rest, {}>>();

console.log({ isDevEnvironnement });

const kyselyDb = new Kysely<Database>({ dialect: createPgDialect(databaseUrl) });

const success = await importTool({
"dbConfig": {
"dbKind": "kysely",
"kyselyDb": kyselyDb
},
"externalSoftwareDataOrigin": externalSoftwareDataOrigin,
"botAgentEmail": botAgentEmail,
"listToImport": listToImport ?? []
});

success ? console.log("Core API initialized") : console.error("Error");
}
Loading