Automatically subscribe to an observable within an Rx stream - kotlin

I have the following code:
Completable.fromCallable { messagesBO.deleteAllGroupsForMessage(messageId) }
.andThen { Completable.fromAction { messagesBO.storeMessageGroups(messageToGroups) }.subscribe() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
},
{ error -> }
))
I have a second Completable:
Completable.fromAction
and I need to subscribe to this in order for the function inside fromAction to run. But this seems to not be a clean way of doing this.
I don't necessarily need to use a Completable as I'm not returning anything in the onComplete. Is there some other way to call a function and have it automatically subscribed to? I could in fact have multiple andThen(s) and would like to chain them together.
UPDATE:
Here is one solution, although I'm not convinced it's the best:
Observable.fromCallable { messagesBO.deleteAllGroupsForMessage(messageId) }
.flatMapCompletable { Completable.fromAction { messagesBO.storeMessageGroups(messageToGroups) } }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
},
{ error -> }
))

Turns out that it's simpler than I thought. Just using map will automatically run the code without any need to create an observable:
Observable.fromCallable { messagesBO.deleteAllGroupsForMessage(messageId) }
.map { messagesBO.storeMessageGroups(messageToGroups) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
},
{ error -> }
)

Related

Ktor Route level plugin intercepting all calls

I've written a small plugin to respond 403 to requests that don't have a userId field in JWT token
class LoggedInUserAuthConfiguration(
)
val LoggedInUserAuthPlugin =
createRouteScopedPlugin(name = "LoggedInUserAuthPlugin", ::LoggedInUserAuthConfiguration) {
with(pluginConfig) {
on(AuthenticationChecked) { call ->
call.principal<JWTPrincipal>()?.let {
call.userId ?: call.respond(HttpStatusCode.Forbidden)
} ?: call.respond(HttpStatusCode.Unauthorized)
}
}
}
I've written 2 functions to use this plugin but none of them work only on route level
fun Route.withLoggedInUser(build: suspend PipelineContext<Unit, ApplicationCall>.() -> Unit) {
install(LoggedInUserAuthPlugin) {}
handle { build() }
}
fun Route.authenticateLoggedInUser(build: suspend Route.() -> Unit) {
install(LoggedInUserAuthPlugin) {}
handle { this#authenticateLoggedInUser.build() }
}
I'm using them like this
fun Route.addRoute() {
authenticateLoggedInUser {
route("/endpoint") {
post {
...
}
get {
...
}
}
}
}
OR
fun Route.addRoute() {
route("/endpoint") {
method(HttpMethod.Post) {
withLoggedInUser {
...
}
}
method(HttpMethod.Get) {
withLoggedInUser {
...
}
}
}
}
This is working OK for the required route, but other routes are being intercepted by this plugin too
I've checked that installIntoRoute() is being called in ktor source
if (this is Route && plugin is BaseRouteScopedPlugin) {
return installIntoRoute(plugin, configure)
}
Firstly, the authenticateLoggedInUser definition is incorrect because you build a route (its children) in a handler. The build function must be called only once while routing is being built. The handler is called each time a matching request is made.
fun Route.authenticateLoggedInUser(build: Route.() -> Unit) {
install(LoggedInUserAuthPlugin) {}
build()
}
Secondly, in your first use case of the authenticateLoggedInUser inside the Route.addRoute method, the plugin is installed into a route where this method is called. Here is an example where your plugin affects the /another route:
authenticate("auth-jwt") {
addRoute()
get("/another") {
call.respondText { "OK" }
}
}
// ...
fun Route.addRoute() {
authenticateLoggedInUser {
route("/endpoint") {
post {
call.respondText { "post" }
}
get {
call.respondText { "get" }
}
}
}
}
To solve this problem, install your plugin into individual routes or the /endpoint route:
fun Route.addRoute() {
route("/endpoint") {
authenticateLoggedInUser {
post {
call.respondText { "post" }
}
get {
call.respondText { "get" }
}
}
}
}

Blind Transfer in JSSIP

I have been trying to make a blind transfer on a ongoing call.
Below is the code i have implemented:
transfersession(ext) {
this.rtcSession.refer('sip:' + ext + '#' + serveraddress);
}
Can someone tell is there something more I have to write?
The above code disconnects the ongoing call and adds the call to he queue.
What mistake am I doing? Thanks in advance.
This is my code to make a blind transfer
function makeBlindTransfer(numberToTransfer) {
let eventHandlers = {
requestSucceeded: function (e) {
console.log("Transferencia realizada con exito");
},
requestFailed: function (e) {
console.log("Transferencia fallo");
},
trying: function (e) {
console.log("trying", e);
},
progress: function (e) {
console.log("progress", e);
},
accepted: function (e) {
console.log("accepted", e);
},
failed: function (e) {
console.log("failed", e);
},
};
try {
ssession.refer(numberToTransfer, {
eventHandlers,
extraHeaders: [`Contact: <sip:${dest}#yourhost:yourport>`],
});
} catch (err) {
console.log("no pudimos realizar su solicitud");
}
}
you can check in the documentation too:
https://jssip.net/documentation/2.0.x/api/refer_subscriber/
https://jssip.net/documentation/2.0.x/api/session/#method_refer
Other side should support refer. However, that can be insecure, so disabled by most of providers.
Anyway, you should learn how to use tcpdump/wireshark and check sip trace.

What's the best way to test redux-saga's `all` effect?

I have a saga which currently has a yield all(...) and I'm trying to figure out how to test to see that I'm actually invoking all() with the correct functions. Here's a stripped-down version of what I'm working with:
function* start() {
// I'd prefer not to start the status polling and the listening for
// the cancellation until after the request has been submitted, but
// I'm having trouble figuring out how to do that. So I'm just going
// to listen for 'em all up front here until I'm smarter.
yield all([
waitForCreateRequest(),
waitForPollStatus(),
waitForCancelRequest(),
])
}
function* waitForCreateRequest() {
while ( true ) {
try {
const { payload } = yield take('CREATE_REQUEST')
// ...
} catch ( error ) {
// ...
}
}
}
function* waitForPollStatus() {
while ( true ) {
try {
const { payload } = yield take('POLL_STATUS')
// ...
} catch ( error ) {
// ...
}
}
}
function* waitForCancelRequest() {
while ( true ) {
try {
yield take('CANCEL_REQUEST')
// ...
} catch ( error ) {
// ...
}
}
}
The test that I wrote (using Mocha and bdd-lazy-var) goes something like this:
describe('MySaga', () => {
describe('*start()', () => {
subject(start())
it('calls `all()` with the correct functions', () => {
expect($subject.next().value).to.eql(all([
waitForSubmitExportRequest(),
waitForPollExportStatus(),
waitForCancelExportRequest(),
]))
})
})
})
There is no output--it just hangs...and then I get a "JavaScript heap out of memory" error.
If I console.log($subject.next().value) instead:
describe('MySaga', () => {
describe('*start()', () => {
subject(start())
it.only('foo', () => {
console.log($subject.next().value)
})
})
})
This is what I get:
MySaga
*start()
{ '##redux-saga/IO': true,
ALL:
[ GeneratorFunctionPrototype { _invoke: [Function: invoke] },
GeneratorFunctionPrototype { _invoke: [Function: invoke] },
GeneratorFunctionPrototype { _invoke: [Function: invoke] } ] }
✓ foo
So I'm not sure what's going on here.
Countless Google searches didn't really turn up anything useful, and the closest SO post that I found (how to test redux-saga all effect using jest) was also unhelpful.
Is it a typo that your start function is not a generator function?
Anyway. Can you try to rewrite your start function like this:
function* start() {
yield all([
call(waitForCreateRequest),
call(waitForPollStatus),
call(waitForCancelRequest),
])
}
Now your test could look like:
it('calls `all()` with the correct functions', () => {
expect($subject.next().value).to.eql(all([
call(waitForSubmitExportRequest),
call(waitForPollExportStatus),
call(waitForCancelExportRequest),
]))
})

How to return a promise from subscribe in angular 5

I want to ask that how can we return a promise from the subscribe function.
Here is the code:
A.ts
makeHttpRequest() {
return this.http.get('https://example.com/login');
}
B.ts
class B {
constructor(private a: A) {
this.a.makeHttpRequest().subscribe(data => {
//How to return a promise from here
});
}
}
I have provided a very abstract level of code if someone is facing any issue to understand it please let me know.
I have developed the solution of question asked above:
class B {
constructor(private a: A) {
return new Promise((resolve,reject)=>{
this.a.makeHttpRequest().subscribe(data => {
resolve(true);
}, (err)=> {
resolve(false);
});
});
}
}

How to access nested functions in Vue.js?

Say, we have a Vue.js component built this way:
export default {
watch: {
// vars
}
},
methods: {
functionOne: function() {
function nestedFuncOne(p, q) {
// doing something
}
},
functionTwo: function() {
function nestedFuncTwo(r, s) {
// doing something
}
nestedFuncOne(param1, param2); // how to call it?
}
},
(...)
How should an inner function from the first method be called from inside of second method? this seems not to give desired output here.