I am trying to use Asterisk ARI to watch for bridge-related events. I am using Asterisk 13.6.0.
Specifically, I want to know when a bridge has been created or destroyed, and when a user (channel) has joined or left the bridge. On my server, bridges are created dynamically when someone dials in, and destroyed automatically when the last member leaves the bridge.
Using the node-ari-client library from the Asterisk project, and following some of their example code, this is what I have so far.
var client = require("ari-client");
var util = require("util");
client.connect("http://localhost:8088", "username", "password")
.then(function (ari) {
ari.once("StatisStart", channelJoined);
function channelJoined (event, incoming) {
incoming.on("BridgeCreated", function(event, bridge) {
console.log(util.format("Bridge created: %s", bridge.id));
});
incoming.on("BridgeDestroyed", function(event, bridge) {
console.log(util.format("Bridge destroyed: %s", bridge.id));
});
incoming.on("ChannelEnteredBridge", function(event, channel) {
console.log(util.format("Bridge was joined by: %s", channel.id));
});
incoming.on("ChannelLeftBridge", function(event, channel) {
console.log(util.format("Bridge was joined by: %s", channel.id));
});
}
ari.start("bridge-watcher");
})
.done();
I expected that the .on() handlers would print to the console when the various events occurred. However, calling into a bridge, leaving a bridge, nothing is ever printed to console.
If it matters, here's the output of npm ls showing which versions I'm using. Node is v0.10.36.
├─┬ ari-client#0.5.0
│ ├── backoff-func#0.1.2
│ ├── bluebird#2.9.34
│ ├── node-uuid#1.4.1
│ ├─┬ swagger-client#2.0.26
│ │ ├── btoa#1.1.1
│ │ └─┬ shred#0.8.10
│ │ ├── ax#0.1.8
│ │ ├── cookiejar#1.3.1
│ │ ├── iconv-lite#0.2.11
│ │ └── sprintf#0.1.1
│ ├── underscore#1.6.0
│ └─┬ ws#0.4.31
│ ├── commander#0.6.1
│ ├── nan#0.3.2
│ ├── options#0.0.5
│ └── tinycolor#0.0.1
├── bluebird#3.1.1
└─┬ util#0.10.3
└── inherits#2.0.1
Specifically, I want to know when a bridge has been created or
destroyed, and when a user (channel) has joined or left the bridge. On
my server, bridges are created dynamically when someone dials in, and
destroyed automatically when the last member leaves the bridge.
Remember: the primary purpose of ARI is to build your own dialplan applications, not to monitor the entirety of Asterisk. As such, by default, your external application is not subscribed to the resources in Asterisk. As the Channels in a Stasis Application section explains:
Resources in Asterisk do not, by default, send events about themselves to a connected ARI application. In order to get events about resources, one of three things must occur:
The resource must be a channel that entered into a Stasis dialplan application. A subscription is implicitly created in this case. The subscription is implicitly destroyed when the channel leaves the Stasis dialplan application.
While a channel is in a Stasis dialplan application, the channel may interact with other resources - such as a bridge. While channels interact with the resource, a subscription is made to that resource. When no more channels in a Stasis dialplan application are interacting with the resource, the implicit subscription is destroyed.
At any time, an ARI application may make a subscription to a resource in Asterisk through application operations. While that resource exists, the ARI application owns the subscription.
If you're expecting to get events automatically for resources in Asterisk that channels are using outside of the bridge-watcher application, you won't get them unless you do one of two things:
Explicitly subscribe to the resources using the applications resource. This works well for resources that are relatively static and/or long lived, such as Endpoints, static Bridges (such as those used for Conferences), Mailboxes, and Device States. It does not work well for transitory resources.
In Asterisk 13.6.0 and later, you can now subscribe to all event sources when you connect your WebSocket. In node-ari-client, you would do the following:
ari.start(bridge-watcher, true);
You should note however that even when you are subscribed to all resources, you don't explicitly own them. You merely can watch them all automatically. The notion of ownership is very important in ARI, particularly as it pertains to what you can and cannot do to channels, and when. The wiki pages I've linked provide some reasonable documentation for how this works.
Related
I am trying to redirect the URL to a custom 404 page in remix.run but not able to do so. I have a url structure something like this -
app/
├── routes/
│ ├── $dynamicfolder/
│ │ ├── index.tsx
│ │ ├── somepage.tsx
│ │ ├── $.tsx
│ └── index.tsx
└── root.tsx
I have a certain number of pages under $dynamicfolder and they are accessible like this -
"https://example.com/xx/" (This is to access the index.tsx, I have 2 fixed values that are
passed in "$dynamicfolder", let's say xx and xy),
"https://example.com/xx/somepage" (This is to access the other page)
When some other random value is passed in $dynamicfolder, let's say "yy", like this -
"https://example.com/yy/"
then I want that to be handled by $.tsx which is also inside $dynamicfolder. Unfortunately, that's not happening and it is throwing an obvious error.
I am accessing the value of $dynamicfolder in $dynamicfolder/index.tsx using useParams() hook. I just want to redirect the page to 404 when any other value apart from xx and xy is passed.
I did follow the remix docs, Splat URLs and Dynamic routes parameters but maybe I am doing some kind of mistake that I am not able to catch.
It is also possible that I might be doing it in the wrong way as I am new to remix.run. Any help would be appreciated. Thanks.
In your loader, check the params and throw new Response('Not found', 404) as needed. Throwing a response will render the closest <CatchBoundary>
In your root route, export a <CatchBoundary> to display your custom 404 error.
https://remix.run/docs/en/v1/guides/not-found#root-catch-boundary
Is there a recommended way to enforce deployment order via specific apps using TurboRepo? I know you can specify that all child dependents run first, but that results in undesired behavior in my scenario.
Here is an example of my file structure:
├── apps
│ ├── backend
│ └── web
├── packages
│ ├── assets
│ ├── config
│ ├── design-system
│ ├── hooks
│ └── utils
And here is the command I'm running to deploy:
yarn turbo run deploy:ci --filter=...[origin/main] --dry-run
In my scenario, I'd like my apps/backend to deploy before apps/web because web relies on output from the backend. I thought about using the following turbo.json:
{
"$schema": "https://turborepo.org/schema.json",
"baseBranch": "origin/main",
"pipeline": {
"deploy:ci": {
"dependsOn": ["^deploy:ci"],
"outputs": [".sst/**", ".build/**", ".expo/**"]
}
}
}
However, while this works if I add backend as a devDependency of web, it also results in backend always being rebuilt (even when none of its dependencies have changed). This is because if I change packages/hooks (which backend does not rely on), it will try to deploy packages/utils because hooks uses the utils package. This waterfalls and causes it to try to deploy backend because backend uses utils.
I'd also like to note that only the apps/* contain deploy:ci methods, so there is really no need for it to try to deploy changes to any package/* dependencies.
My end goal would look like the following:
Change packages/hooks
Detect change in packages/hooks and trigger deploy:ci for apps/web (which has hooks as a dependency)
Or
Changes packages/utils
Detect change in packages/utils and try to deploy both apps/backend and apps/web because they both rely on utils
I've tried replacing
"dependsOn": ["^deploy:ci"],
with
"dependsOn": [],
and this does result in only the correct packages being rebuilt, but the deploy order is willy-nilly. Ideally, I'd have this latter behavior while still enforcing backend always goes before web.
I have a Node.js with Express.js app. I have folders like such:
src
/models
/router
/store
/api/v1
index.js
My router folder has a file called index.router.js which contains my app's routes e.g:
import UserAPI from '../api/v1/user.api.js'
expressRouter.post('/register', function async function (req, res) {
await UserAPI.registerUser({
EMail: req.body.EMail,
Password: req.body.Password,
Name: req.body.Name
});
The above is a route to an API so it went into my index.router.js file. To perform an API action on this endpoint, I created another file for API functionality called user.api.js and it would contain something like:
async function registerUser({EMail, Password, Name}) {
// Import method from model file and perform DB action
});
As the application has grown I have come to wonder whether I have made it too complex and created an unecessary layer with a separate file of user.api.js which could possibly be refactored to be part of index.router.js.
What I do not understand is what is the standard practice of file structuring an API for scalability and should the API endpoints be in a separate file/folder of api/v1, api/v2 or should they be part of the router?
One thing that could be advantagous of having separate api files is resuability. Because it only contains functions and no routing, the functions could be reused across many different router files.
You have basically re-invented the MVC design pattern.
It's not overly complicated. It is considered good practice and encouraged.
C
Traditionally, what you call Routers is usually called the Controller. The job of the controller is simply to handle routing, handle argument parsing (request body, query parameters, is user logged in etc.) and sometimes handle validation. This is exactly what Express is designed to do. And Express allows controller functionality like authentication and validation to be refactored into middlewares.
Note: Sometimes you will see tutorials on the internet where people separate controllers and routes. My personal recommendation is do not do this. Express routing has been designed to be perfect for writing controllers. About the ONLY reason to separate them is if you have two different URLs that do the exact same thing. In my opinion that is better handled by a redirect.
M
Traditionally what you call API is called the Model. The model is your traditional collection of objects or data structures that you learned to program with. The model is what performs the application logic. Normally classes or modules that implement models are not labeled with anything. For example a user model would not be called UserAPI or UserModel but simply called User. However, what you name things is just a convention. Stick with what makes sense to you.
V
The final part of MVC is the View. In Express the view is simply res.json() or res.render() with its associated HTML template. This part is 99% already written by Express developers - you just need to tell the view functions what to send to the front-end.
Your architecture is good
There are very good reasons for separating the model (API) from the controller (router). First is that it allows you to solve your problems without polluting your core logic with parameter parsing logic. Your models should not need to worry about weather the user is logged in or how data is passed to it.
Second is that it allows you to use your model (API) logic outside of Express. The most obvious use for this is unit testing. This allows you to unit test your core logic without the web parts of the code. I also usually write utility scripts that I can use to do things like create a new user, dump user data, generate authentication token so I can use it with Postman etc.
For example you can create a script like:
#! /usr/bin/env node
// register-user.js
import UserAPI from '../api/v1/user.api.js'
UserAPI.registerUser({
EMail: process.argv[2],
Password: process.argv[4],
Name: process.argv[3]
})
.then(x => {console.log(x); process.exit()})
.catch(console.error);
Which you can then execute on the command line to create new users without needing to run the server:
$ ./register-user.js myemail#address.com 'My Name' 123456
It looks like your software is already structured according to MVC. Keep it that way. It will make maintaining and modifying the software a little easier.
API and router are two different things and even from different worlds.
Most of the applications are composed of two basic building blocks, UIs and APIs. UIs is supposed to be for humans and APIs for machines. You can have 0-n UIs and 0-n APIs. There is no rule for that.
For example UI you might have a webpage for common visitiors, application for paying visitors or those who bought your product and application for administrators. Those are three separate UIs. If one is malfunctioning, others are working.
The other example are APIs. There can be separate API for each of these UI. Also there can be APIs for third parties or other microservices of your own system. And again, if one API doesn't work, it doesn't impact others.
Router is the design pattern for URL control. Or a specific implementation of the design pattern if you wish.
While both UIs and APIs might require URL control, the same pattern can be used in both parts of the application system. But it doesn't mean it should be in the same folder. Things for building blocks should be in separate folders. Router, unlike the model, is not a common thing you would share among building blocks.
The folder structure you present here, Im sure you have seen it somewhere on the interent. But I do not consider it mature. I would consider something like that more mature:
├── model
├── website-ui
│ ├── routers
│ ├── templates
│ └── index.js // this is router
├── website-api
│ ├── user
│ │ └── index.js // this might be a router (API dependent
│ ├── item
│ │ └── index.js // this might be a router
│ └── index.js // this is router
├── index.js
└── main-router.js // this is router
Usually you don't even do main-router like that, because this responsibility goes often to load balancer outside of Nodejs. But everyone must start somewhere. This implementation is easy to upgrade later.
Do not confuse multiple APIs with API versions. In the best case scenario, you never want API versions, ever. You would proceed like this:
├── website-api
│ ├── user-old
│ │ └── index.js
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ ├── index-v1.js
│ └── index-v2.js
or that:
├── website-api-v1
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ └── index.js
├── website-api-v2
│ ├── user
│ │ └── index.js
│ ├── item
│ │ └── index.js
│ └── index.js
You can't tell now. And you shouldn't care. When you do changes in API, you do them backward compatible. If you can't do that anymore, it means you have done some critical mistakes in the past or large business changes comes in. This is not predictable.
One thing that could be advantagous of having separate api files is resuability.
Yes, but you can't tell now.
Regarding to your other questions. Stick to the SOLID rinciples. Each part of the code should have one specific purpose.
When I see your router folder, I have no idea what is there. Well I know routers, but routers of what? There can be everything, yet nothing. Thus not easily extensible = bad.
When I look at my structure, I can more easily predict what is in there.
You should design your architecture regarding to the purpose and not the specific implementations. Lets say you have two APIs because you have two purposes. Are they both REST or GraphQL? Can I share code and remove duplicities? Not that important. Sharing code is actually very dangerous if not done properly. Shared code is the worst part to refactor and it often doesn't provide as many advantages.
... I have come to wonder whether I have made it too complex...
Depends, is it a 14 days project? Yes you did. Is it for a year or more? You should go even deeper.
In visual studio cod, How to navigate from feature to step definition. Do we need any additional plugins or any configuration needs to be added. I have downloaded the Cucumber (Gherkin) Full Support plugin but still cannot navigate from .feature to the step definition.
The documentation of Cucumber (Gherkin) Full Support plugin has the explanation for it.
You need to add the below in your settings:
{
"cucumberautocomplete.steps": [
"test/features/step_definitions/*.js",
"node_modules/qa-lib/src/step_definitions/*.js"
],
"cucumberautocomplete.syncfeatures": "test/features/*feature",
"cucumberautocomplete.strictGherkinCompletion": true
}
cucumberautocomplete.steps => provide the path of the step definitions.
cucumberautocomplete.syncfeatures => provide the path of the feature files
After this(might be after a restart), cmd + click(on mac) would take to the step definition.
Thanks,
Naveen
Having installed the extension alexkrechik.cucumberautocomplete, I tried modifying the settings from both the UI of the extension and its corresponding settings JSON (by default, mine were in ~/.config/Code/User/settings.json). But this didn't work because I got this error in the *.feature files: Was unable to find step for "Some feature description".
I noticed I had skipped a step mentioned in the extension docs... By default, it was getting the settings.json from my userspace and not my work(project)space.
For me, the solution was to go to the root directory of my project (usually outside of /src, where you have the package.json and node_modules/) and create a .vscode/ folder. Then, create a settings.json file and paste there the cucumberautocomplete configuration with the paths relative to this brand new file.
Below I show a schema:
myProject/
├── node_modules
├── package.json
├── subdir1
│ ├── src
│ └── test
│ └── e2e
│ └── src
│ ├── features
│ │ └── myfeature1.feature
│ ├── mypageobject1.po.ts
│ └── steps
│ └── mystep1.step.ts
└── .vscode
└── settings.json
An example of configuration would be:
{
"editor.detectIndentation": false,
"window.zoomLevel": 0,
"cucumberautocomplete.steps": [
"subidr1/test/e2e/src/steps/*.steps.ts"
],
"cucumberautocomplete.syncfeatures": "subidr1/test/e2e/src/feature/*.feature"
}
Note that you could use **/*.steps.ts and **/*.feature paths but every time the extension settings file changes, when you Ctr + Click on a feature description, you will need to wait for the editor to resolve the paths. Otherwise, there is no waiting time.
I need to create a large server with node.js that is as scalable as possible and suitable for serious production. In my project, I'm also using typescript to make sure my app is as scalable as possible
I have seen surfing the internet that virtually all projects are structured by grouping files for their purpose/role. Instead of all these articles, I read only twice the recommendation to structure the app with autonomous components.
So what is the best structure for great scalability?
└───src
├───bin
├───components
│ ├───Auth
│ ├───Post
│ ├───Profile
│ └───User
├───config
│ └───keys
└───database
or
└───src
├───config
│ └───components
├───controllers
├───models
│ └───plugins
├───routes
│ └───api
├───utils
└───validation
└───forms
You should use the second one, because it separates better your code and makes it more readable. You should also consider making a tests folder and a .env file