CQRS: Return created ID - cqrs

I need to return the ID of the entity a command creates to the client.
(For example to redirect from new-potato to potatoes/:id)
I cannot create the ID on the client, for example because:
The quality of client random ID cannot be ensured.
Short, sequential IDs are required.
Can I return the ID when I submit the command?
For example the command is
{
type: "CreatePotato",
eyes: 3
}
the returned payload is
{
data: {id: 1001}
}
and the event persisted is
{
type: "PotatoCreated",
id: 1001,
eyes: 3
}

You can just send an ID with a command:
{
id: 1001,
type: "CreatePotato",
eyes: 3
}
Since in a good system ids should be unique, immutable and never carry any semantic, then you can just generate some GUID, CUID or whatever you are using, right in the command, and assume that if command has succeded, your new entity ID is one that you have sent.

Related

Best practices with connecting data from 2 models

I've got two models: Note and Profile. Note contains foreign key of connected profile as you can see below.
Note: {
profile_id: String,
date: String,
content: String,
}
Profile: {
id: String,
name: String,
profilePicture: String
}
I want to get all notes and also name and profile picture of note.
In this situation should I:
get all notes and all profiles and then join them locally in for loop,
get all notes and then in for loop ask DB for name and picture of matching profile,
other option
Which way is recomended?
Take a look at mongoose's Populate. You can declare a Schema property with type: Schema.Types.ObjectId, ref: 'Profile'. When you run a Query you can .populate() this field with the corresponding document.

How to write JOIN in graphQL or get result from multiple types - AWS App sync iOS

I am using AWS AppSync for a chat app in one of the my applications. We are able to do setup and basic query successfully.
In one of the case I need to write a customized GraphQL query so that I can have additional data using reference of one type from another. For example, I can have allMessageGroup from a user and also allMessages from a particular group.
Now I want to add the last message in the group and its sender with the list of all message group just like what's app home page.
But I am not able to understand how make JOIN or write such query which give mixed results based on Conversation/Message/User types/table.
Platform:iOS
Language: Swift
For detail below is my Schema and API/Query I am using
Schema
type Conversation {
conversation_cover_pic: String
conversation_type: String!
createdAt: String
id: ID!
messages(after: String, first: Int): MessageConnection
name: String!
privacy: String
}
type Message {
author: User
content: String!
conversationId: ID!
createdAt: String
id: ID!
recipient: User
sender: String
}
type MessageConnection {
messages: [Message]
nextToken: String
}
Query
query getUserConversationConnectionThroughUser($after: String, $first: Int)
{
me
{
id
__typename
conversations(first: $first, after: $after)
{
__typename
nextToken
userConversations
{
__typename
userId
conversationId
associated
{
__typename
userId
}
conversation
{
__typename
id
name
privacy
messages
{
__typename
id
conversationId
content
createdAt
sender
isSent
}
}
}
}
}
}
It sounds like you need multiple requests to one or more datasources to fulfill this graphQL query. In this case, you can use AppSync's pipeline resolver feature.
With pipeline resolvers, you can create multiple functions, each of which can use the results of the previous function and query a database. These functions run in an order you specify.
An example of something you could do with a pipeline resolver:
One function will query the chat group database
A second function will use the results of the chat group to fetch messages
Consolidate all the results into one graphQL response containing group information and messages
Here is the documentation for pipeline resolvers: https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html

RESTful API design advice on getting all A associated with B

I'm trying to design a RESTful API as a side project.
I am also using MongoDB as database
(I'm new to NoSQL design, so I need help, If I have misunderstanding in how documents should be designed).
I have example entities as following:
Event {
id: string
name: string
date: date
location: location
subgroups: group[]
}
Group {
id: string
owners: user[]
members: user[]
parentEvent: event
posts: post[]
}
User {
id: string
Name: string
attendingGroups: group[]
owningGroups: group[]
}
post {
id: string
parentgroup: Group
}
location {
id: string
city: string
}
For above example,
Should I have a designated get call for having all groups associated with the user?
or should I get a user and get the associated groups from the user retrieved?
Depends how you design it. You can embed resources in other resources to save you from N+1 select problem, nothing is against with that.
Hal+json format is the format you should be embedding resources.
In REST you can even have ?_embed=groups parameter to embed or not.
Embedding or not embedding is up to your applications needs, not embedding way = you should design a filter like /groups?user=eralpb to get the groups. Or sub-resources work as well like /users/eralpb/groups should only return my groups.

Store contents with rest proxy giving incorrect count

ExtJS 5.1.x, with several stores using rest proxy.
Here is an example:
Ext.define('cardioCatalogQT.store.TestResults', {
extend: 'Ext.data.Store',
alias: 'store.TestResults',
config:{
fields: [
{name: 'attribute', type: 'string'},
{name: 'sid', type: 'string'},
{name: 'value_s', type: 'string'},
{name: 'value_d', type: 'string'}
],
model: 'cardioCatalogQT.model.TestResult',
storeId: 'TestResults',
autoLoad: true,
pageSize: undefined,
proxy: {
url: 'http://127.0.0.1:5000/remote_results_get',
type: 'rest',
reader: {
type: 'json',
rootProperty: 'results'
}
}
}
});
This store gets populated when certain things happen in the API. After the store is populated, I need to do some basic things, like count the number of distinct instances of an attribute, say sid, which I do as follows:
test_store = Ext.getStore('TestResults');
n = test_store.collect('sid').length);
The problem is that I have to refresh the browser to get the correct value of 'n,' otherwise, the count is not right. I am doing a test_store.load() and indeed, the request is being sent to the server after the .load() is issued.
I am directly querying the backend database to see what data are there in the table and to get a count to compare to the value given by test_store.collect('sid').length);. The strange thing is that I am also printing out the store object in the debugger, and the expected records (when compared to the content in the database table) are displayed under data.items array, but the value given by test_store.collect('sid').length is not right.
This is all done sequentially in a success callback. I am wondering if there is some sort of asynchronous behavior giving me the inconsistent results between what is is the store and the count on the content of the store?
I tested this with another store that uses the rest proxy and it has the same behavior. On the other hand, using the localStorage proxy gives the correct count consistent with the store records/model instances.
Here is the relevant code in question, an Ajax request fires off and does its thing correctly, and hit this success callback. There really isn't very much interesting going on... the problem section is after the console.log('TEST STORE HERE'); where I get the store, print the contents of the store, load/sync then print the store (which works just fine) and then finally print the length of uniquely grouped items by the sid attribute (which is what is not working):
success: function(response) {
json = Ext.decode(response.responseText);
if(json !== null && typeof (json) !== 'undefined'){
for (i = 0, max = json.items.length; i < max; i += 1) {
if (print_all) {
records.push({
sid: json.items[i].sid,
attribute: json.items[i].attribute,
string: json.items[i].value_s,
number: json.items[i].value_d
});
}
else {
records.push({
sid: json.items[i].sid
})
}
}
//update store with data
store.add(records);
store.sync();
// only add to store if adding to search grid
if (!print_all) {
source.add({
key: payload.key,
type: payload.type,
description: payload.description,
criteria: payload.criteria,
atom: payload.atom,
n: store.collect('sid').length // get length of array for unique sids
});
source.sync();
}
console.log('TEST STORE HERE');
test_store = Ext.getStore('TestResults');
test_store.load();
test_store.sync();
console.log(test_store);
console.log(test_store.collect('sid').length)
}
// update grid store content
Ext.StoreMgr.get('Payload').load();
Ext.ComponentQuery.query('#searchGrid')[0].getStore().load();
}
For completeness, here is the data.items array output items:Array[2886]
which is equivalent count of unique items grouped by the attribute sid and finally the output of console.log(test_store.collect('sid').length), which gives the value from the PREVIOUS run of this: 3114...

Rest API get resource id by field

What is a correct rest way of getting a resource ID by a field, for example a name. Take a look at the following operations:
GET /users/mike-thomas
GET /users/rick-astley
I don't want to use these operations at my API end, instead I want to write an API operation that will get me the ID when submitting a field (name in the case of users) for example:
GET /users/id-by-field
Submitted data:
{
"fullName": "Mike Thomas"
}
Return data:
{
"data": {
"id": "123456789012345678901234"
}
}
What you want is known as an algorithmic URL where the parameters for the algorithm are passed as URL parameters:
GET /users?name="Mike Thomas"
Advantages are that you are using the "root" resource (users) and the search parameters are easily extended without having to change anything in the routing. For example:
GET /users?text="Mike"&year=1962&gender=M
where text would be searched for in more than just the name.
The resultant data would be a list of users and could return more than the identification of those users. Unless fullName uniquely identifies users, that is what you need to allow for anyway. And of course the list could contain a single user if the parameters uniquely identified that user.
{
users: [
{
id: "123456789012345678901234",
fullName: "Mike Thomas",
dateJoined: 19620228
}
, {
id: "234567890123456789012345"
fullName: "Rick Astley",
dateJoined: 19620227
}
]
}