Skip to content
Merged
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: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ subprojects {
DependencyResolution.defaultRepositories(repositories)

val spineBaseVersion: String by extra
val spineTimeVersion: String by extra
val spineCoreVersion: String by extra

dependencies {
Expand Down Expand Up @@ -196,7 +197,7 @@ subprojects {
// Transitive dependencies from `core-java` may have different (older) versions.
"io.spine:spine-base:$spineBaseVersion",
"io.spine:spine-testlib:$spineBaseVersion",
"io.spine:spine-time:$spineBaseVersion"
"io.spine:spine-time:$spineTimeVersion"
)
}
}
Expand Down
16 changes: 8 additions & 8 deletions client-js/main/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ import {Observable} from 'rxjs';
*
* Represents a command acknowledgement callback.
*
* @property {!parameterlessCallback} onOk the callback to run when the command is handled properly
* @property {!consumerCallback<Error>} onError the callback to run when the command cannot be
* handled due to a technical error
* @property {!consumerCallback<Message>} onRejection the callback to run when the command cannot
* be handled properly because of the business
* rejection
* @property {!parameterlessCallback} onOk
* the callback to run when the command is handled properly
* @property {!consumerCallback<Error>} onError
* the callback to run when the command cannot be handled due to a technical error
* @property {!consumerCallback<Message>} onImmediateRejection
* the callback to run when the command is denied execution due to a business rejection
*/

/**
Expand Down Expand Up @@ -304,7 +304,7 @@ export class Client {
* @param {?consumerCallback<CommandHandlingError>} errorCallback
* a callback receiving the errors executed if an error occurred when sending command
* @param {?consumerCallback<Rejection>} rejectionCallback
* a callback executed if the command was rejected by Spine server
* a callback executed if the command is denied processing due to a business rejection
* @see CommandHandlingError
* @see CommandValidationError
*
Expand All @@ -314,7 +314,7 @@ export class Client {
this.command(commandMessage)
.onOk(acknowledgedCallback)
.onError(errorCallback)
.onRejection(rejectionCallback)
.onImmediateRejection(rejectionCallback)
.post();
}
}
29 changes: 20 additions & 9 deletions client-js/main/client/command-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const NOOP_CALLBACK = () => {};
* client.command(logInUser)
* .onOk(_logOk)
* .onError(_logError)
* .onImmediateRejection(_warnAboutRejection)
* .observe(UserLoggedIn.class, ({subscribe, unsubscribe}) => {
* subscribe(event => _logAndUnsubscribe(event, unsubscribe));
* setTimeout(unsubscribe, EVENT_WAIT_TIMEOUT);
Expand Down Expand Up @@ -66,7 +67,7 @@ export class CommandRequest extends ClientRequest {
this._commandMessage = commandMessage;
this._onAck = NOOP_CALLBACK;
this._onError = NOOP_CALLBACK;
this._onRejection = NOOP_CALLBACK;
this._onImmediateRejection = NOOP_CALLBACK;
this._observedTypes = [];
}

Expand All @@ -82,7 +83,7 @@ export class CommandRequest extends ClientRequest {
}

/**
* Runs the callback if the command could not be handled by the Spine server due to the
* Runs the callback if the command could not be handled by the Spine server due to a
* technical error.
*
* @param {!consumerCallback<CommandHandlingError>} callback the callback to run
Expand All @@ -94,17 +95,23 @@ export class CommandRequest extends ClientRequest {
}

/**
* Runs the callback if the server responded with the `rejection` status on a command.
* Runs the callback if the server responded on a command with an immediate rejection.
*
* Note that with the current Spine server implementation it's rare for the command to be
* rejected right away. In most cases, the command will be acknowledged with the `OK` status and
* only then lead to a business rejection. You can check this scenario using the `observe` method.
* The immediate rejection means the command did not pass the command filters set up in the
* bounded context and was disqualified from execution right away.
*
* A typical example of this would be the command not passing filters due to user permissions
* being not broad enough.
*
* Please note that this rejection is different to a "normal" rejection when the command is
* acknowledged with the `OK` status and then reaches the handler method which processes it. Such
* rejections can be tracked using the `observe(...)` method of this request.
*
* @param {!consumerCallback<spine.core.Event>} callback
* @return {this} self for method chaining
*/
onRejection(callback) {
this._onRejection = callback;
onImmediateRejection(callback) {
this._onImmediateRejection = callback;
return this;
}

Expand All @@ -130,7 +137,11 @@ export class CommandRequest extends ClientRequest {
*/
post() {
const command = this._requestFactory.command().create(this._commandMessage);
const onAck = {onOk: this._onAck, onError: this._onError, onRejection: this._onRejection};
const onAck = {
onOk: this._onAck,
onError: this._onError,
onImmediateRejection: this._onImmediateRejection
};
const promises = [];
this._observedTypes.forEach(({type, consumer}) => {
const originFilter = Filters.eq("context.past_message", this._asOrigin(command));
Expand Down
2 changes: 1 addition & 1 deletion client-js/main/client/commanding-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class CommandingClient {
: new CommandHandlingError(message, error));
break;
case Status.StatusCase.REJECTION:
onAck.onRejection(responseStatusProto.getRejection());
onAck.onImmediateRejection(responseStatusProto.getRejection());
break;
default:
onAck.onError(
Expand Down
2 changes: 1 addition & 1 deletion client-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "spine-web",
"version": "1.5.23",
"version": "1.5.25",
"license": "Apache-2.0",
"description": "A JS client for interacting with Spine applications.",
"homepage": "https://spine.io",
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/js-tests/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "client-js-tests",
"version": "1.5.23",
"version": "1.5.25",
"license": "Apache-2.0",
"description": "Tests of a `spine-web` JS library against the Spine-based application.",
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/js-tests/test/firebase-client/fetch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('FirebaseClient "fetch"', function () {
client.command(command)
.onOk(() => reportTaskCreated())
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.post();
});

Expand Down Expand Up @@ -220,7 +220,7 @@ describe('FirebaseClient "fetch"', function () {
client.command(command)
.onOk(selectAndCheckFailed)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.post();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import TestEnvironment from '../given/test-environment';
import {CommandHandlingError, CommandValidationError, ConnectionError} from '@lib/index';
import {CreateTask} from '@testProto/spine/web/test/given/commands_pb';
import {TaskCreated} from '@testProto/spine/web/test/given/events_pb';
import {TaskCannotBeCreated} from '@testProto/spine/web/test/given/rejections_pb';
import {Task} from '@testProto/spine/web/test/given/task_pb';
import {fail} from '../test-helpers';
import {client, initClient} from './given/firebase-client';
Expand Down Expand Up @@ -64,7 +65,7 @@ describe('FirebaseClient command sending', function () {
client.command(command)
.onOk(fetchAndCheck)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.post();
});

Expand Down Expand Up @@ -92,7 +93,7 @@ describe('FirebaseClient command sending', function () {
malformedBackendClient.command(command)
.onOk(fail(done, 'A command was acknowledged when it was expected to fail.'))
.onError(checkError)
.onRejection(fail(done, 'A command was rejected when an error was expected.'))
.onImmediateRejection(fail(done, 'A command was rejected when an error was expected.'))
.post();
});

Expand All @@ -118,7 +119,33 @@ describe('FirebaseClient command sending', function () {
client.command(command)
.onOk(fail(done, 'A command was acknowledged when it was expected to fail.'))
.onError(checkError)
.onRejection(fail(done, 'A command was rejected when an error was expected.'))
.onImmediateRejection(fail(done, 'A command was rejected when an error was expected.'))
.post();
});

it('runs `onImmediateRejection` callback when the command is rejected by a filter', done => {
const command = TestEnvironment.createTaskCommand({
withPrefix: 'spine-web-test-send-command',
named: 'Reject this command on purpose',
describedAs: 'Spine Web need integration tests',
rejectCommand: true
});
const taskId = command.getId();
const checkRejection = rejection => {
try {
const rejectionType = Type.forClass(TaskCannotBeCreated);
const unpacked = AnyPacker.unpack(rejection.getMessage()).as(rejectionType);
assert.ok(unpacked);
assert.equal(unpacked.getId().getValue(), taskId.getValue());
done();
} catch (e) {
fail(done, e.message)
}
};
client.command(command)
.onOk(fail(done, 'A command was acknowledged when it was expected to fail.'))
.onError(fail(done, 'An error occurred when a business rejection was expected.'))
.onImmediateRejection(checkRejection)
.post();
});

Expand All @@ -134,7 +161,7 @@ describe('FirebaseClient command sending', function () {

client.command(command)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.observe(TaskCreated, ({subscribe, unsubscribe}) => {
subscribe(event => {
const packedMessage = event.getMessage();
Expand Down Expand Up @@ -181,7 +208,7 @@ describe('FirebaseClient command sending', function () {

client.command(command)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.observe(Unknown)
.post()
.then(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Single-tenant client', function () {
singleTenantClient
.command(cmd)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.observe(UserInfoAdded, ({subscribe, unsubscribe}) =>
subscribe(event => {
const eventMessage = AnyPacker.unpack(event.getMessage()).as(userInfoAddedType);
Expand Down
20 changes: 10 additions & 10 deletions integration-tests/js-tests/test/firebase-client/subscribe-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('FirebaseClient subscription', function () {
commands.forEach(command => {
client.command(command)
.onError(fail(done))
.onRejection(fail(done))
.onImmediateRejection(fail(done))
.post();
});
})
Expand Down Expand Up @@ -99,7 +99,7 @@ describe('FirebaseClient subscription', function () {
client.command(renameCommand)
.onOk(() => console.log(`Task '${taskId}' renamed.`))
.onError(fail(done, 'Unexpected error while renaming a task.'))
.onRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.post();
}
}
Expand Down Expand Up @@ -131,7 +131,7 @@ describe('FirebaseClient subscription', function () {
client.command(createCommand)
.onOk(() => console.log(`Task '${createCommand.getId().getValue()}' created.`))
.onError(fail(done, 'Unexpected error while creating a task.'))
.onRejection(fail(done, 'Unexpected rejection while creating a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while creating a task.'))
.post();
})
.catch(fail(done));
Expand Down Expand Up @@ -171,7 +171,7 @@ describe('FirebaseClient subscription', function () {
client.command(renameCommand)
.onOk(() => console.log(`Task '${taskIdValue}' renamed for the first time.`))
.onError(fail(done, 'Unexpected error while renaming a task.'))
.onRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.post();
}
});
Expand All @@ -197,7 +197,7 @@ describe('FirebaseClient subscription', function () {
.onOk(() => console.log(`Task '${taskIdValue}' renamed for the second time.`))
.onError(fail(done,
'Unexpected error while renaming a task.'))
.onRejection(fail(done,
.onImmediateRejection(fail(done,
'Unexpected rejection while renaming a task.'))
.post();
}
Expand All @@ -207,7 +207,7 @@ describe('FirebaseClient subscription', function () {
client.command(createCommand)
.onOk(() => console.log(`Task '${taskIdValue}' created.`))
.onError(fail(done, 'Unexpected error while creating a task.'))
.onRejection(fail(done, 'Unexpected rejection while creating a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while creating a task.'))
.post();
})
.catch(fail(done));
Expand Down Expand Up @@ -245,7 +245,7 @@ describe('FirebaseClient subscription', function () {
.onOk(() =>
console.log(`Task '${taskIdValue}' is renamed to '${nameAfterRenamed}'.`))
.onError(fail(done, 'Unexpected error while renaming a task.'))
.onRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.post();
}
});
Expand All @@ -268,7 +268,7 @@ describe('FirebaseClient subscription', function () {
client.command(createCommand)
.onOk(() => console.log(`Task '${taskIdValue}' created.`))
.onError(fail(done, 'Unexpected error while creating a task.'))
.onRejection(fail(done, 'Unexpected rejection while creating a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while creating a task.'))
.post();
})
.catch(fail(done));
Expand Down Expand Up @@ -312,7 +312,7 @@ describe('FirebaseClient subscription', function () {
client.command(createCommand)
.onOk(() => console.log(`Task '${createCommand.getId().getValue()}' created.`))
.onError(fail(done, 'Unexpected error while creating a task.'))
.onRejection(fail(done, 'Unexpected rejection while creating a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while creating a task.'))
.post();

const renameCommand = TestEnvironment.renameTaskCommand({
Expand All @@ -322,7 +322,7 @@ describe('FirebaseClient subscription', function () {
client.command(renameCommand)
.onOk(() => console.log(`Task '${taskId}' renamed.`))
.onError(fail(done, 'Unexpected error while renaming a task.'))
.onRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.onImmediateRejection(fail(done, 'Unexpected rejection while renaming a task.'))
.post();
});

Expand Down
10 changes: 7 additions & 3 deletions integration-tests/js-tests/test/given/test-environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export default class TestEnvironment {
* withPrefix?: String,
* named?: String,
* describedAs: String,
* assignedTo: UserId
* assignedTo: UserId,
* rejectCommand: Boolean
* }}
*
* @return {CreateTask}
Expand All @@ -59,7 +60,8 @@ export default class TestEnvironment {
withPrefix: idPrefix,
named: name,
describedAs: description,
assignedTo: userId
assignedTo: userId,
rejectCommand: reject
}) {
const taskId = this.taskId({value: id, withPrefix: idPrefix});

Expand All @@ -76,7 +78,9 @@ export default class TestEnvironment {
if (!!userId) {
command.setAssignee(userId);
}

if (reject) {
command.setReject(true);
}
return command;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class UserTasksTestEnvironment extends TestEnvironment {
createTaskAcknowledged();
})
.onError(createTaskFailed)
.onRejection(createTaskFailed)
.onImmediateRejection(createTaskFailed)
.post();
}

Expand All @@ -85,7 +85,7 @@ export class UserTasksTestEnvironment extends TestEnvironment {
client.command(command)
.onOk(resolve)
.onError(reject)
.onRejection(reject)
.onImmediateRejection(reject)
.post();
})
}
Expand Down
Loading