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

new version of handling besluit information #45

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

Rahien
Copy link
Collaborator

@Rahien Rahien commented Sep 13, 2024

Description

Besluiten are now handled as described on the gitbook: https://app.gitbook.com/o/-MP9Yduzf5xu7wIebqPG/s/UYHyp4MV7ApSjjQn2DUx/algemene-informatie/besluit-harvesting

How to test

Use the mock route to receive besluit instances in the consumer graph. Verify that indeed they are processed as per the gitbook.

After each mock route check, run the clear decisions endpoint: localhost:8082/mock/clear-decisions

The mock routes are configured for use in provincie vlaams brabant as an example bestuurseenheid. Because of a delay of delta message processing you need to wait 10s before you see the notifications.

mock routes exist for:

Links to other PR's

Copy link
Contributor

@JonasVanHoof JonasVanHoof left a comment

Choose a reason for hiding this comment

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

Just went over the code, mostly some things about variables or doing the same in a different way.

graph: string,
) {
const id = uuidv4();
const intervalUri = `http://data.lblod.info/id/tijdsintervallen//${id}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it need to be //?

Comment on lines 534 to 552
if (sparqlresult?.artikel) {
return sparqlresult.artikel;
return {
besluit: sparqlresult.artikel.value,
link: sparqlresult.link.value,
};
}

return null;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you prefer that the returning value of this function is of a different format?

Would remove the if and just add a ? after sparqlResult.artikel?.value. Than you do have to change the logic where this method is called to check if (findDecisionForMandataris(URI).besluit) instead of just the return value

}

return null;
}

export async function updatePublicationStatusOfMandataris(
mandataris: Term,
mandataris: string,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we create a URI type so we work with these and errors can be thrown when it is not a URI?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

afaik a uri is just a string

Comment on lines +549 to 560
mandataris: sparqlEscapeUri(mandataris),
status: sparqlEscapeUri(status),
mandatarisType: sparqlEscapeTermValue(TERM_MANDATARIS_TYPE),
Copy link
Contributor

Choose a reason for hiding this comment

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

If we change mandataris to escapeUri we should also do it for the type

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

there is a separate story to remove all uses of term from the mandataris service.

Comment on lines +43 to +45
// keep these mandataris instances in the database instead of memory
// so if we crash we know they should still be processed
// wait BUFFER_TIME to process the mandataris so we are reasonably sure that we have all the info
Copy link
Contributor

Choose a reason for hiding this comment

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

👍🏻

);
console.log(
`|> Found ${incomingTriples.length} triples in the staging graph for mandataris.`,
async function isValidMandataris(mandataris: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

*mandatarisUri

Comment on lines +62 to +63
? ('ontslag' as const)
: ('aanstelling' as const),
Copy link
Contributor

Choose a reason for hiding this comment

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

Or do we use an enum for this?

} LIMIT ${BESLUIT_BATCH_SIZE}`;

const result = await querySudo(query);
return result.results.bindings.map((binding) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

getSparqlResults.map(... *

Comment on lines +11 to +13
const safeMandatarisUri = sparqlEscapeUri(mandatarisUri);
const safeGraph = sparqlEscapeUri(graph);
const safeIntervalUri = sparqlEscapeUri(intervalUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

uniform: do we want to do separate escapes or use the const escaped = { ... } as did before?

mandataris: Term,
): Promise<Term | null> {
const mandatarisSubject = sparqlEscapeTermValue(mandataris);
mandataris: string,
Copy link
Contributor

Choose a reason for hiding this comment

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

mandatarisUri*

Copy link
Contributor

@JonasVanHoof JonasVanHoof left a comment

Choose a reason for hiding this comment

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

Tried out the mock routes

  • Karel's: besluiten processing

    • First mock route looks to be working correctly ✅
    • second ✅
    • third a notification is created for the unknown fractie ✅
    • fourth: unknown mandaat error => checkIfMinimalMandatarisInfoAvailable returned and not throwing an error.. ❌
    • incomplete person, error message => checkIfMinimalMandatarisInfoAvailable returned and not throwing an error.. ❌
    • different fraction name => checkIfMinimalMandatarisInfoAvailable returned and not throwing an error.. ❌
    • new beleidsdomein, info message => checkIfMinimalMandatarisInfoAvailable returned and not throwing an error.. ❌

    It seems that the minimal info is often not valid because of the graph and after that the publication status is still changed to bekrachtigt?

Im open to check these last mock calls togheter!

(quad) =>
quad.graph.value.startsWith(BESLUIT_STAGING_GRAPH) &&
quad.predicate.value.startsWith(
'http://data.vlaanderen.be/ns/mandaat#bekrachtigt',
Copy link
Contributor

Choose a reason for hiding this comment

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

In the docs it just says to process mandaat:bekrachtigtAanstellingVan (first point). A mandataris should only be set to bekrachtigd when it is an aanstelling?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess it makes sense to handle both, even if it not mentioned in the docs, but I think the outcome should be different, but now they seem to be handled the exact same way?

for (const match of batch) {
await safeProcessMandatarisForDecisions(match);
}
await cleanInstancesFromQueue(batch);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we also need to remove the batch from the staging graph?

@Rahien Rahien force-pushed the karel/lmb-758-rework-besluit-info branch from 873ac7a to f93e979 Compare November 15, 2024 15:39
Copy link
Contributor

@bfidlers bfidlers left a comment

Choose a reason for hiding this comment

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

The besluiten logic seems pretty solid, few remarks here and there. The code is not always as readable, a few more descriptive function names would help.

Few issues however with older logic, a method disappeared which is still used and a method seems to mix ids and uris, but this might just be the name that is misleading.

@@ -49,3 +50,4 @@ const errorHandler: ErrorRequestHandler = function (err, _req, res, _next) {
app.use(errorHandler);

notificationBekrachtigdMandataris.start();
setTimeout(() => cronjob.start(), 10000);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably remove this when actually merging this I guess?

Copy link
Contributor

Choose a reason for hiding this comment

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

Bit confused about these http vs https prefixes, both seem to be in use in our application.

Comment on lines +156 to +169
async function findDecision(mandatarisUri: string): Promise<string | null> {
const isMandataris = await mandataris.isValidId(mandatarisUri);
if (!isMandataris) {
throw new HttpError(
`Mandataris with id ${mandatarisId} not found.`,
`Mandataris with id ${mandatarisUri} not found.`,
STATUS_CODE.BAD_REQUEST,
);
}
const decision = await findDecisionForMandataris({
type: 'uri',
value: mandatarisId,
} as Term);
const decision = await findDecisionForMandataris(mandatarisUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

Bit confused about this, what is it? a uri or an id, because some statements seem to imply the first, other the second.

@@ -11,15 +11,15 @@ PREFIX euro: <http://data.europa.eu/m8g/>
PREFIX euvoc: <http://publications.europa.eu/ontology/euvoc#>
PREFIX ext: <http://mu.semte.ch/vocabularies/ext/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX generiek: <https://data.vlaanderen.be/ns/generiek#>
PREFIX generiek: <http://data.vlaanderen.be/ns/generiek#>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure about this generiek prefix, if I look in the app, sometimes we seem to use http and sometimes https.

Comment on lines +5 to +12
export function getIdentifierFromPersonUri(uri: string) {
const personBaseUri = 'http://data.lblod.info/id/personen/';
if (!uri.includes(personBaseUri)) {
return uuidv4();
}

return uri.replace(personBaseUri, '').trim();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not used anymore.

);
console.log(
`|> Found ${incomingTriples.length} triples in the staging graph for mandataris.`,
async function isValidMandataris(mandataris: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Function name is not really descriptive. It does more than it says. It checks whether the madataris is valid and whether it has a besluit. Maybe you could call it isValidMandatarisWithBesluit ?


export const BESLUIT_STAGING_GRAPH =
process.env.BESLUIT_STAGING_GRAPH ||
'http://mu.semte.ch/graphs/besluiten-consumed';

export const TERM_STAGING_GRAPH = {
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't used anymore.

GRAPH ?bestuurseenheidGraph {
?mandaat a mandaat:Mandaat .
}
?bestuurseenheidGraph ext:ownedBy ?bestuurseenheid.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this used so you don't have to exclude all special graphs?

PREFIX ext: <http://mu.semte.ch/vocabularies/ext/>
PREFIX person: <http://www.w3.org/ns/person#>

SELECT * {
Copy link
Contributor

Choose a reason for hiding this comment

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

The * seems a bit inefficient if you only need the bestuurseenheidGraph.

OPTIONAL {
?graph ext:ownedBy ?bestuurseenheid.
}
FILTER(?graph = <http://mu.semte.ch/graphs/public> || BOUND(?bestuurseenheid))
Copy link
Contributor

Choose a reason for hiding this comment

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

I think public now also has the ext:ownedBy?

@bfidlers
Copy link
Contributor

We need to do a second pass over the code to check we always exclude the besluiten staging graph. Now it is often implicit and sometimes the ext:ownedBy is used. But we need to double check this and make it more explicit.

@bfidlers
Copy link
Contributor

Testing:

@bfidlers
Copy link
Contributor

bfidlers commented Nov 18, 2024

Noticed two more things.

  1. We always update the publication status, is this correct? For example if we throw an error because the mandate in the besluit is unknown, do we still want to bekrachtig the mandataris with that uri?
  2. I feel like we never actually create the link to the besluit?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants