How to effectively use Worker, WorkflowClient - cadence-workflow

Product Use Case - Our product has a typical use case where we will be having n no of users. Each user will have n no of workflows and each workflow can be run at any time(n of time).
I hope this is a typical use case of any workflow product.
can I use a domain to differentiate users (I mean to say that creating a domain per user)?
Can I create one WorkflowClient per user to serve all his workflow executions? Or for each request should I need to create one WorkflowClient? which one is a recommended approach?
What is the recommended approach in creating Worker objects to poll task list?
Please don't mistake me If I have asked anything meaningless

can I use a domain to differentiate users (I mean to say that creating a domain per user)?
Yes, especially when these users are working in different teams or product, using different domain will avoid workflowName/IDs conflicting each others, and also assign independent number of quotas for managing traffic.
Can I create one WorkflowClient per user to serve all his workflow executions? Or for each request should I need to create one WorkflowClient? which one is a recommended approach?
Use one WorkflowClient for each domain, but let all WorkflowClients on the same instance share the same TChannelService to save the TCP connection.

I would start with a single namespace (domain) for all users. Unless your users directly operate their workflow implementations it doesn't buy you much to use multiple namespaces.

Related

Is it possible to combine userRolesHeader with roles defined in realm.properties?

So I'm sending all users through apache with mod_auth_kerb. All users come in with a default userRolesHeader of users.
I'd like to add extra roles for specific accounts, but I'm not seeing a good way to do that. If you could define the users in realm.properties and it would combine with the userRolesHeader, that would be useful.
Is there another way to do this? I don't see how it can be done with apache alone since REMOTE_USER isn't available during if/else logic processing.
#rundeck
rundeck.security.authorization.preauthenticated.userNameHeader=X-Forwarded-Uuid
rundeck.security.authorization.preauthenticated.userRolesHeader=X-Forwarded-Roles
#apache
RequestHeader set "X-Forwarded-Uuid" %{REMOTE_USER}s
RequestHeader set X-Forwarded-Roles users
Internally Rundeck gets only one method once, if you configure Rundeck to get the users from the realm.properties file, Rundeck seeks the roles from that file. Currently You can combine methods but the user/role in different methods doesn't.

How to design REST API with one action but two different meanings?

Given the example of a shop API with an orders resource. You would want to delete one order by id
DELETE /orders/:orderId
Under the hood you run an update query and set canceled to true. But what if
A customer calls this endpoint:
You need a canceledByCustomer database flag
No additional permissions are required
An administrator calls this endpoint?
You need a rejectedByAdministrator database flag
Additional permissions are required
Would you keep the endpoint posted above and check internally, if the calling user tries to cancel the order of another user and if true, this is a reject action?
Would you add two query parameters cancel and reject and one of them MUST be true and one of them MUST be null/false?
Would you violate the design rules, create two different endpoints and add verbs to them like so?
DELETE /orders/:orderId/cancel => customer can call it
DELETE /orders/:orderId/reject => only administrators can call it
Does someone know about the best practises for such "domain driven" problems?
API endpoints don't have to correlate on what happens closer to the core, for example in your Aggregate Root or CommandHandler. In my opinion, make the API routes as verbose as possible, which means creating their own separate routes for each use case. Push the logic on what database flag to use (canceledByCustomer vs rejectedByAdministrator) closer down to the entity.

Saas: Single-instance vs Multi-instance vs Single-tenant vs Multi-tenant?

I've been reading about instances and tenants and in the Saas architecture. My questions are as follows (please correct anything that you notice I've gotten wrong with any of the following terms):
1) Instance: Is an instance of a piece of software just a copy of that software with its own database? Is there anything more to it than that?
2) Tenant: Is a tenant a user / group of users that share a common set of access privileges to an individual instance?
3) Single-instance: If a Saas provider offers single-instance service, does this mean that they create only a single instance of their software? Or does it mean that there could be multiple instances, but that each instance can serve multiple tenants? If so, is single-instance the same as multi-tenant?
4) Multi-instance: Does this mean that each instance can serve only one tenant, or can there be multiple instances that each serve multiple tenants? ie. Can a multi-instance service be either single-tenant or multi-tenant?
5) Single-tenant: Does this just mean that an individual instance can serve only one tenant, or does it also imply that there are multiple instances? ie. Can a single-tenant service be both single-instance and multi-instance?
6) Multi-tenant: Does this just mean that an individual instance can serve multiple tenants, or does it imply that there is only a single instance? ie. Can a multi-tenant service be both single-instance and multi-instance?
7) To sum up: Can you have single-instance+single-tenant, single-instance+multi-tenant, multi-instance+single-tenant, and multi-instance+multi-tenant?
I'm going to write from my direct experience:
1) simple answer is 'yes'.
2) nearly yes: there will probably be refined access rights, say an administrator or two, and general users.
3) they're providing you with just one instance of that module, which will be single tenant.
4) they're providing you with multiple instances of that module, which will be single tenant.
5) I would use single-tenant to refer to the server hosting the instances is used by only one tenant. This might be done for perceived security benefits, or the server is running on a time zone that is non-standard for SaaS provider, like staying on UTC all year round.
6) I would use multi-tenant to refer to the server hosting the instances is used by more than one tenant. This tends to be more cost effective and probably just as secure as single-tenant.
7) yes, no, yes, yes.

Nested/Chained Resources in Rest

This is a more of an architectural question. And I am rather new two Rest.
Let's assume these resources /offers and /offers/:id.
And the offer does have a single connection to an organization.
My first thought was creating a resource: /offers/:id/organization
This would be singular, because it feels unnatural to call the resource in plural, when there is always only one element returned.
First question: Would you always use plural no matter what?
This /offers/:id/organization/:id seems to be useless, because there is only one organization linked to the offer.
To make things complicated. The organizations need to be a separate resource as well: /organizations and /organizations/:id.
So basically I have to ways to achieve my goal.
I could get the /offers. And then with the retrieved organizationId get /organization/:id. Or I could nest the organization into the offer that I get everything in one request either /offers or /offers/:id.
The second option would potentially get rid of /offers/:id/organization(s).
Except I wanted to get the organization by the offerId and not be the organizationId. (One organization has cn offers).
Second question: When there is a standalone resource, i.e /organization, should I bother of implementing a nested resource as well /offer/:id/organization(s).
There is also the issue of how to implement the services (i am using jersey) if the organization is available at /offers/:id/organization(s) but that is probably a Question on its own.
Any thoughts?
As usually, it depends.
If your offer has only a single organization
/offers/:id/organization
is fine, because that is how your domain-model works.
This is different at
/organizations/:id/offers/:id
because, so I suspect, an organization could have multiple offers. So the id makes sense, also the resource /organizations/:id/offers, what are all offers for this organization.
You could implement
/offers/organization/:id
what could redirect to /organizations/:id/offers because it is semantically the same.

Strategy to generate auto increment unique number in CQ

I have a requirement to create CQ pages programmatically. But the challenge is that the page name/uri should be autogenerated combination of a string + unique number (eg. PT2000, PT2001).
Can someone tell me a way way to generate an autoincrement-id/constant in CQ in a way that the id's are unique even with multiple concurrent request?
Use a service that provides you with the ID and that manages the counter inside a volatile instance variable to make sure that state changes by one thread are immediately communicated to all other threads.
This should do the trick as long as your can guarantee that your implementation runs on a single author node. In a cluster scenario you additionally have to care about executing it only on one node.
i'd suggest creating a service that manages its counters somewhere in the repository, and also acts as a jcr EventListener. the service should listen for NODE_ADDED events on parent nodes of type cq:Page, and once onEvent is called, it can assigned the unique id at that point. you'd want to use synchronization obviously so that overlapping calls to onEvent() won't use up the same id.
You can use a GUID, Graphic User ID, the ID generated has a great probablity of uniqueness.
See wiki reference http://en.wikipedia.org/wiki/Globally_unique_identifier
and to create GUID:
Create a GUID in Java
This will ease you effort to verify the number is unique so just generate the ID and create the pages with that ID.
Doesn't AEM automatically append numbers to same name pages?
If it doesn't, then presumably this would fail, at which point you start over with the next number. Best guess should be enough in this case.