<!-- 
RSS generated by JIRA (1001.0.0-SNAPSHOT#100246-sha1:7a5c50119eb0633d306e14180817ddef5e80c75d) at Thu Feb 08 23:08:55 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>FOLIO Jira</title>
    <link>https://folio-org.atlassian.net</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>1001.0.0-SNAPSHOT</version>
        <build-number>100246</build-number>
        <build-date>07-02-2024</build-date>
    </build-info>

<item>
            <title>[FOLIO-869] Aggregator module</title>
                <link>https://folio-org.atlassian.net/browse/FOLIO-869</link>
                <project id="10290" key="FOLIO">FOLIO</project>
                    <description>&lt;p&gt;We discussed a simple aggregator module in Cph. Summarize design here.&lt;/p&gt;</description>
                <environment></environment>
        <key id="79340">FOLIO-869</key>
            <summary>Aggregator module</summary>
                <type id="10002" iconUrl="https://folio-org.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10322?size=medium">New Feature</type>
                                            <priority id="10002" iconUrl="https://dev.folio.org/assets/jira-priority/jira-p3.svg">P3</priority>
                        <status id="1" iconUrl="https://folio-org.atlassian.net/images/icons/statuses/open.png" description="The issue is open and ready for the assignee to start work on it.">Open</status>
                    <statusCategory id="2" key="new" colorName="blue-gray"/>
                                    <resolution id="-1">Unresolved</resolution>
                                                        <assignee accountid="-1">Unassigned</assignee>
                                                                <reporter accountid="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a">Heikki Levanto</reporter>
                                    <labels>
                    </labels>
                <created>Fri, 29 Sep 2017 10:38:47 +0000</created>
                <updated>Fri, 18 Jan 2019 12:47:56 +0000</updated>
                                                                                <due></due>
                            <votes>0</votes>
                                    <watches>2</watches>
                                                    <timespent seconds="16200">4 hours, 30 minutes</timespent>
                                <comments>
                                                            <comment id="190936" author="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a" created="Fri, 29 Sep 2017 10:49:49 +0000"  >&lt;p&gt;The idea is to build something not unlike graphQL, but simplified to the bare minimum that we can get away with. Main points:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Read-only access to any Okapi module&lt;/li&gt;
	&lt;li&gt;Schemaless entry point that takes a Json structure that defines what is to be fetched, and what is to be expanded&lt;/li&gt;
	&lt;li&gt;Multi-level expansion, but on fixed paths (userid -&amp;gt; user record -&amp;gt; loan records -&amp;gt; item records) But not (user  id -&amp;gt; proxy record -&amp;gt; another user id -&amp;gt; another user record -&amp;gt; proxy record -&amp;gt; ... aritrary depth user record)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In some cases it makes sense to extend the main record with the expanded data, for example when getting a loan record that has a userid, put a whole user record next to it. In other cases less so, for example when getting a list of notes about an item, each of them has a userid who created the note, but these are often the same. Then it is better to return a list of notes with just the userids, and a separate map from userids to user records.&lt;/p&gt;

&lt;p&gt;We need to be able to expand in both directions: Starting from a loan record, find the userid, and get the matching user. Or, starting from a user record, take the userid, and find all loans that the user has (and probably expand the items in those too)&lt;/p&gt;</comment>
                                                            <comment id="190941" author="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a" created="Fri, 29 Sep 2017 11:24:01 +0000"  >&lt;p&gt;Over the lunch we agreed that the way is to post the aggregation rules to this module, which will then create endpoints that provide the aggregated data, for example notes-with-user-names. The aggregation rules can be part of a moduleDescriptor, either in the back-end module (mod-notes can provide the notes-with-user-names), or in the UI module, depending what the UI needs.&lt;/p&gt;</comment>
                                                            <comment id="190946" author="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a" created="Fri, 29 Sep 2017 12:26:55 +0000"  >&lt;p&gt;Simple example: endpoint notes-with-users gets notes, and expands the userid into user records. The /notes endpoint returns an object that contains a &lt;tt&gt;notes&lt;/tt&gt; array of note records.&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;endpoint: /notes-with-users
get: /notes
aggregate {
  each: notes as {note}
  get: /users/{note.metadata.creatorUid}
  into {note}.userdata
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
</comment>
                                                            <comment id="190947" author="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a" created="Fri, 29 Sep 2017 12:48:31 +0000"  >&lt;p&gt;A more complex example:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;endpoint: /loans-with-detail?{query},{limit},{maxlocs}
get: /loans?query=$query&amp;amp;limit=$limit
aggregate {
  each: loans[*] as {loan}
  get: /items/{loan.item}
  into: {loan}.itemdetails
  aggregate {
    each: {loan}.itemdetails.locations[*] as {loc}
    get: /locations/{loc.locationcode}?limit={maxlocs}
    into {loc}.locationdetails
  }
}

aggregate {
  join: loans[*].userid with &quot; OR &quot; as {userlist}
  get: /users?query=userid any {userlist}
  into: users[]
  aggregate {
    each: users as {usr}
    get: /perms/?query=user={usr.userid}
    into: {usr}.perms
  }
}
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This iterates over all loans, and expands the items in them by looking up locations. Then it takes all the userids, joins them into one list, does a lookup on that, and then iterates over each user looking up permissions too.  The join functionality may not be needed in version 1 of the aggregator, but it is here as an example of the directions we may expand the definition language. &lt;/p&gt;

&lt;p&gt;Of course the language will be proper Json, we don&apos;t want to parse our own string representation of it.&lt;/p&gt;</comment>
                                                            <comment id="190951" author="712020:38d1a08f-86a8-4df2-9191-239b16b0a81a" created="Fri, 29 Sep 2017 12:57:33 +0000"  >&lt;p&gt;The first implementation will be a stand-alone module with only in-memory data, to get a proof of concept up and running quickly. Then one that persists its data, and Okapi inegration, so we can define aggregation endpoints in ModuleDescriptors, using the redirect facility, with a new header that tells what the original path was.&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10000" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummarycf">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10057" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
                        <customfieldname>Development Team</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue key="10144"><![CDATA[Core: Platform]]></customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        <customfield id="customfield_10019" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|hzy08v:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_10020" key="com.pyxis.greenhopper.jira:gh-sprint">
                        <customfieldname>Sprint</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    </customfields>
    </item>
</channel>
</rss>