vjekob / al-objid Goto Github PK
View Code? Open in Web Editor NEWManage object IDs in multi-user environments with mind-boggling simplicity.
License: MIT License
Manage object IDs in multi-user environments with mind-boggling simplicity.
License: MIT License
Create .objidconfig
with this content:
{
"idRanges": [
{
"from": 50000,
"description": "Test"
}
]
}
Restart Ninja (not necessary, but to start off with a clean slate).
Diagnostics window will show "Missing property: to"
Now, change .objidconfig
to this:
{}
The diagnostics don't update.
Diagnostics should update after the document has been emptied.
You are working on a project where you have multiple id ranges in app.json. This could be e.g. if you code your app and tests in the same app and then remove the tests in a build pipeline or maybe you have multiple ranges assigned to your app.
When assigning a new id AL Object ID Ninja suggest the first available ID. If I want to assign an ID from another range, I need to do that manually and then synchronize with AL Object ID Ninja backend.
AL Object ID Ninja should suggest the first available id from all the ranges in app.json.
Right now (v1.0.3), Ninja synchronizes app IDs per app. This means that every app submits its own ranges definitions and tracks its own consumption of IDs. This covers the basic needs of development teams who develop and maintain simple BC apps, especially monolithic ones.
However, for mature development teams developing an app hierarchy with dependencies across multiple apps (which makes an awful lot of sense for anything more complex than a pocket calculator), multiple apps will consume IDs from the same pool of IDs to prevent object collision when dependencies are installed.
The current behavior of Ninja just won't cut it. If Ninja is not capable of tracking object IDs across entire pools of apps, it is simply unusable except for simple app scenarios.
This is how I intend to handle this.
There will be three commands:
Create app pool
: it will create a new app pool in the back end and will return the id. It will also update the .objidauth
file (new name is due!) and store that id in there.Join app pool
: it will ask the user for pool id, and will store that pool id in .objidauth
.Leave app pool
: opposite of point 2.When sending any requests to the back end, Ninja will include the pool id along the app id whenever there is pool id info in .objidauth
.
Pools will be also maintained in the back end - it will know which apps belong to which pool. When a pool is created, the app from where it was created will be automatically added to the pool. Also, when an app joins or leaves the pool, the back-end cache is updated accordingly.
When getNextId request is processed, if pool id is not included for an app that is known to belong to a pool, there will be a warning in the front end about this.
When syncIds request is processed, if pool id is not passed along the app id, back end refuses to process the request. This situation indicates that the local repo sending the request is probably using an outdated .objidauth
and is probably not in sync with latest master
branch, so this error will force it to update.
This is how I intend to solve this. This feature is an absolute must for mature development teams.
If you have any comments, about the above description, or think it won't get the job done and something else is needed. please let me know in the comments.
Hi, app authorization doesn't work in multiroot workspace.
Steps are:
unauthorized
Additionally id sync throws error
Fully Automated
This all works with single app opened as folder (not as workspace).
In this example I actually have only one al app in App
folder. Test
and CICD
folders are empty, but error is the same when test app exists. CICD
folder never contains app, it is for yamls only.
Hi,
we struggled to authorise our app to make use of the AL Object ID Ninja, only to find out that it must have been already authorised in the past. I know, you must be getting a lot of these request, but it would be awesome if you could get in touch with us and remove our App ID from the back end, if possible, pretty please.
We tried to work around it, but it simply made matters worse. If there is a way for us to solve it, please let me know.
And thank you for developing the app in the first place. It's been great in the other projects so far!
First, thank you for this wonderful app!
Not sure if you saw my comment on closed ticket #39 but like I mention there, I don't see 2.9.2 anywhere to be installed.
While doing some testing (2.9.1) I notice that if we get the warning for "no more numbers are available. Do you want to synchronize?" and we press Synchronize, it will REPLACE the back end info. Is this intended? It seems dangerous, if we are using a pool, it will only store that app consumption, and not the whole pool.
Also, on a pool, I need to sync each app individually to have all ID's on the back end. I'm wondering if, when on a pool, the synchronize should sync all apps.
Thank you for your work.
Partly, this is related to #41 and it certainly depends on it being done first.
Currently, Backend
class receives app hash as parameter for all back-end operations. Furthermore, it processes app ID and pool ID decisions directly. This class, just like the back end itself, should not even consider pools, it should simply access the hash property that should (as per #41) return pool ID when an app is in a pool.
At this particular point, there is an accidental infinite loop in telemetry during app initialization (not in production, don't worry!) simply because app ID is passed to telemetry from app initialization, but then Backend
class attempts to re-initialize the app because it doesn't know about the app, only about its hash. While this is a simple issue to fix, the root cause is deeper, and is twofold:
ALApp
instances; andALApp
instances should return pool ID from ˙get hash(): string˙
function, if the app belongs to a poolThis would then provide for a much cleaner structure, easier to reuse and extend.
To be able to go live with this tool, I can imagine in project with ongoing development, multiple branches might already have reserved id's on top of the main branch
new function "Add Id" that's similar to sync, but doesn't remove any ids, just adds missing ones.
Cycle through all branches. Like:
Object ID Ninja suggested IDs that were not free. Turns out that I have some .al files with UTF-16 LE and for these files the object ids are not synced. I don't know why these files had UTF-16 encoding and I'm going to change it to UTF-8, I'm just reporting this in case you would like to know.
One my developer is experiencing this error:
We could not detect your current branch. Your repository could be in detached head state. Please, check out to an actual branch, and then retry.
when trying to authorize. We have tried first in workspace with two apps, but even when opening only the folder with one app.
Before I finish writing of this issues, we have tried to update git from 2.19 to latest and it solved the problem. Thus, leaving it here for others having same issue.
I am trying to work in the same workspace as defined in #36 right now and I do see some changes to the behavior of Object Ninja. For instance, the command "Copy ranges from app.json to .objidconfig works. I am using the exact same folder structure and workspace file as described before.
However, when I try to use "Create a simple App Pool", I am getting the error "Cannot read properties of undefined (reading 'manifest')". I would assume that it means that it can't find the objidconfig, but not sure. Based on this assumption, however, I have played a bit with having different files open thinking, I would be able to force the system to use the right paths. Didn't work though.
I also have tried to change the encoding of the app.json file to UTF-8, but this didn't do anything either.
Not sure, if you want me to open an additional issue, but I also tested the "Authorize App" for the test app (second app in the workspace) and while it doesn't throw an error, it doesn't add anything to the .objidconfig, so I am assuming it also can't find it. However, in all of those tests, the proper "active app" is shown in the status bar.
Could you, please, add a way to export range explorer information to CSV file? Sometimes we need to discuss/report/analyze the utilization of ranges in the meetings where using VSC is not easy - and it would be great to be able to export this and be able to convert it into some nice slides...
Hi @vjekob ,
First of all thank you for this cool VSCode extension.
I just imagined that it could be useful that there should be a warning if an new object is not in the customers license.
Sometimes this problem only arises when the new feature request is already in the test-environment of the customer and creates an awkward situation where the customer is informed to buy ore objects while testing it's new feature.
Regards,
Job
At first I have placed the license file in the Project Folder instead of the MainApp Folder. Therefore I specified a path like the following:
{
"bcLicense": "../CustomerLicence.bclicense",
"idRanges": [],
"objectRanges": {
]
}
}
I received no warning or error, but when I checked the developer tools, there was the following error:
TypeError: Cannot read properties of undefined (reading 'uri')
at new BCLicense (c:\Users\kise.vscode\extensions\vjeko.vjeko-al-objid-2.9.1\out\lib\BCLicense.js:36:83)
at ObjIdConfigLinter. (c:\Users\kise.vscode\extensions\vjeko.vjeko-al-objid-2.9.1\out\features\linters\ObjIdConfigLinter.js:211:29)
at Generator.next ()
at fulfilled (c:\Users\kise.vscode\extensions\vjeko.vjeko-al-objid-2.9.1\out\features\linters\ObjIdConfigLinter.js:5:58)
at process.processTicksAndRejections (node:internal/process/task_queues:96:5)
$onExtensionRuntimeError @ mainThreadExtensionService.ts:80
Ninja should be able to assign new object IDs when offline. Intellisense should indicate offline suggestions with a different icon/color, and it should be able to detect when it goes online. After it goes online, it should sync the offline consumption, and should be able to detect if any of offline IDs are still available, and if not, it should re-assign (re-number) those that are not.
First of all, thank you for your work on this great extension. 🙂
If the app.json contains the element "idRange" instead of the required "idRanges" the API requests are failing because of the missing range property.
Since both elements are allowed, the extension should also support both.
On the videos, where you showed how to use Ninja, we can see how easy is to allocate new id of the object.
What about de-allocation?
Let's consider some scenarios:
For now our plan, not perfect, would be:
when creating stable new release - re-sync repo with id's to match master.
But obviously allocations done in "work in progress" (in any branches not yet committed) will be lost and could cause overlapping...
Any suggestions how to handle this?
In an individual workspace, you will get a popup 'Do you want to synchronize' every time when using ctrl+space to get an object id. It doesn't remember when I click No.
Could it remember that I don't want to use Object ID Ninja in a particular workspace?
A feature for app pools, similar to the Range Explorer.
For the app-pool(s) in my current workspace, how much of each range is being used.
Thank you for this great feature (app pools)!
Just added a bunch of repo's, and are looking forward to seeing the results.
Hi Vjeko,
if the injectSemicolon flag is set, then I get the proposal of let's say 4;
. That's fine. But in the unlikely event that at the same time another user consumes the 4
, then I'll get the next number 5
. That's also fine. But currently the code is working like this:
Insert 4;
and then replace the already consumed id 4
afterwards with the new id 5
+ semicolon. So it replaces 4
with 5;
which results in 5;;
Currently, when AL repo is synched with the Azure backend, the under the AppId there is the storage of all used and available id's per this app.
What if to add a tenant and environment from launch.json or better as a separate Ninja configuration (pointing to a production tenant and environment), where PTE will be installed.
If 2+ partners, or even 1 partner with several cooking PTE's will point to the same environment, then service can suggest new range, or at least notify that the chosen range will conflict with other extension.
This will automatically give everyone a value of reducing the risk having same id used in different pte’s even from different partners!
Sometimes, Ninja will warn that Only -57 objects remain for codeunit objects in...
The reason for this is when the back end has object IDs consumption registered for IDs that fall outside ranges defined in app.json
. For example, if app.json
defines range 50000..50010, and there are 50 objects consumed between 60001 and 60050, then Ninja will say that -49 objects remain to be assigned.
Invalid object ID registrations can happen in two know ways in Ninja:
app.json
are modified after some object IDs have already been assigned in ranges that previously were defined in app.json
but now no longer are.app.json
has different contents in different branches, and merge ID synchronization was used to allow development in that other branch.Ninja should always correctly calculate the remaining IDs only for the ranges defined in app.json
. Any actual object IDs assigned outside ranges defined in app.json
should not influence the calculation of remaining IDs. This will give correct available number of objects to developers in all branches.
Hi
Could you return an object with reservation API from your extension "activate" method? I would like to use it from my extension to suggest and reserve ids in object wizards. If you want, I can create a pull request, but we would need to discuss how you would like to do it first (file names, api structure).
It would probably be better if that API class is just a container for other API objects as it will be easier to extend it later, when your extension gets more functionality, i.e. something like this:
class API {
backendAPI: BackendAPI;
}
class BackendAPI {
async getNextNo(uri: vscode.Uri, type: string, commit: boolean): Promise<NextObjectIdInfo | undefined>
async getMultipleNextNos(uri: vscode.Uri, type: string, noOfIds: integer, commit: boolean): Promise<NextObjectIdInfo[] | undefined>
... and maybe some other backed functions here ...
}
User ID information is sent from Ninja to the back end, where it's cached for the purpose of notifications (it feeds the info for " has created " toast messages in VS Code.
However, this information is stored in plain format, making it possible to anyone with access to the back end storage to read. This at minimum violates GDPR, but it also raises unnecessary privacy concerns.
My intent is to encrypt the user ID with a symmetric algorithm in the front end and store it in the back end in encrypted form. The symmetric key has to be something known at all times to front end, but never to back end.
I am thinking of app pool id (#1) or app id (for apps that are not in a pool).
This solves the problem (with app id) because all users working on the same app can always decrypt the user id before showing the notification, while nobody with access to back end can decrypt the content cached there.
However, with pool id it's a bit different. Pool id is always known to the back end, and we have this:
I'll probably just include encryptionKey
property to .objidconfig
file and if it's there, content is encrypted with it, otherwise app id is used. Since .objidconfig
must be a part of the repo, all developers always have access to it.
From DevOps, it might be interesting to be able to build a test whether this person (the one that is running a PR) is using Ninja or not. As such: all IDs in his repo should be reserved. If not: error.
So .. would it be possible to call the backend, and check if an ID (of the added(/changed) is reserved or not? Or any other way?
Think about it .. ;-)
And what if one developer in my team doesn’t want to use it?
Well, then you are on your own. Back to Excel sheets, or yelling, or whatever works better for you.
The problem of the rogue employee, creating a object ID outside AL Object ID Ninja, is that the person behind him/her wil use this object ID again and wil have the problem on the merge of the pull-request.
It would be great to validate in a CD/CD pipeline to be sure the that all the object ID's are requested though AL Object ID Ninja. If not throw a warning, so the developer is forced to resolve that issue in the pull-request.
..if possible a nice-2-have would be that if the object ID that is created still is available it will automatically assign in AL Object ID Ninja
Hi,
not sure if you have seen this (I bet you did):
At least I get a warning in Azure on that topic for the AL Ninja Azure Functions.
Ninja uses app hash to access back-end features. For the back-end, the hash identifies an app. App pools "hijack" this feature by simply replacing the app ID with app pool ID. Since the back-end has no way to tell an app from a pool (and since it doesn't really care if it's an app or a pool) it performs all operations correctly for both apps and pools.
However, in the front end, there is a lot of fumbling around checking if an app is in a pool in a lot of unnecessary places.
Proposed change is this: get property for hash in ALApp
class should return app ID hash if it's an app, or app pool ID if it's an app pool. All places where app pool ID is accessed directly or taken into account for some choices should be refactored. The reason is that there are a lot of places where explicit checking of pool is done, and those places don't really care about pools - they merely care about retrieving correct hash to work on. In great majority of these operations, it's the pool ID that should be used anyway.
This refactoring will reduce the number of places where app pool is worked on explicitly.
However, it carries a big risk of breaking some existing features, so that's why this task here, rather than a simple TODO in the code. This needs to be handled very carefully.
First of all: the logical range feature helps me so much, thanks a lot for that!
I don't know whether it's a bug or feature, but in my case, the range description is missing for my test app (in yellow):
You're seeing a workspace with (main) app and test app.
The range descriptions for the main app are displayed, but the only one from the test app is not.
We are using TableExtensionIDs 57xxx for SalesLine, PurchaseLine... I checked the IDs with "Validate Object IDs againt license".
Ninja says "tableextension 57101 is not included in the license", but they are working fine :-)
As I know you can use any TableExtensionID and you don't have to license them. Is this wrong?
Business Central 18.5. Range 57100-57199 is included in app.json (and objidconfig)
Hi Vjeko.
I have one question, I just started playing around with the backend and I was wondering if there is any method where we can get all the objects ids of an app, without consuming a new object id ?
I know that with the getNext request we get a list of all the objects but that only happens in the POST method and in that situation we are consuming a new id.
Thanks in advance :)
We sometimes want to use differnt Object Id Range for our apps. Especially for Page Extensions.
Since we can't set this in the app.json, maybe this can be added to the logical ID Ranges, that you added recently.
I have been looking into using the AL-Go workspace configuration. When you have this type of workspace, it seems that Object Ninja doesn't understand that this is an AL workspace. The app doesn't activate and when I try to run any of the commands, I am getting errors that either no AL folders open (when trying to create an app pool) or no error, but nothing is happening, when trying to synchronize the object ids and select replace.
The folder structure in that example is:
root (workspace folder)
.AL-Go
App
App.Test
within the first folder, you have some Github specific stuff, in the second folder the app, and in the third folder the test app.
Let me know what you need and I can try to provide you any additional info. If it's just me having some setups not right, please let me know as well.
Thanks for all you do with this "must have" extension!
Hi Vjeko,
In the Overview of AL Object Ninja on the Marketplace there has been this text for a while now:
Note: Automatic detection of object deletion and automatic releasing of freed-up object IDs is currently in development and will be included in the next version.
A new version has now been released, but I don't see this functionality in the change log. When will this be released?
Thank you in advance!
Hi Vjeko
Today I experienced that one of our extensions suddenly will not communicate with the backup.
All the others in the multiroot workspace are working just fine.
I fear someone might have added authentication 'by accident', but no one says that's the case.
Other developers on the team has the same experience.
[2022-02-09T13:26:58.642Z] [Verbose] sending request to https://vjekocom-alext-weu.azurewebsites.net/api/v2/getNext: {"appId":"daa37...","type":"tableextension","ranges":[...]} [2022-02-09T13:26:58.867Z] Sending GET request to /api/v2/getNext endpoint resulted in an error: {"error":"{\n \"errorMessage\": \"Invalid credentials\"\n}","statusCode":401,"headers":{"transfer-encoding":"chunked","content-type":"text/plain; charset=utf-8","server":"Kestrel","date":"Wed, 09 Feb 2022 13:26:58 GMT","connection":"close"}}
Is there a way, where we can see what happened?
Running version 2.2.0, last updated 12.12.2021 18.01.22
Thank you
Right now (v1.0.3) notifications are being pulled from the back end with polling interval of 15 seconds. This is poor man's approach, but to make this cool feature work in time for yesterday's beerinar demo, I had to hack something quickly.
Needless to say, this can't stay that way.
I looked at some frameworks, but haven't really figured out anything useful just yet.
If you have an idea about which push notifications framework I should use, do let me know.
These are requirements:
Any ideas?
I'm posting it as a feature request.
Would it be possible that instead od Workspace(Git Repo) extension has a setting to check the license that resides on SharePoint ?
Regards,
Aleksandar.
Right now, Ninja will see this as two objects:
#if something
codeunit 50001....
#else
codeunit 7013010..
#endif
Also, object ID assignment will occur from the first available range.
Some kind of support for this is needed.
Any ideas how this should behave, functionally?
Looking today into the log console and see:
[2021-09-13T07:57:24.062Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
[2021-09-13T07:57:24.073Z] Executing Sending GET request to /api/v1/getLog endpoint took 351.1608999967575 milliseconds
[2021-09-13T07:57:24.073Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
[2021-09-13T07:57:39.015Z] Executing Sending GET request to /api/v1/getLog endpoint took 119.86720000207424 milliseconds
[2021-09-13T07:57:39.015Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
[2021-09-13T07:57:39.016Z] Executing Sending GET request to /api/v1/getLog endpoint took 241.2812000066042 milliseconds
[2021-09-13T07:57:39.016Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
[2021-09-13T07:57:54.029Z] Executing Sending GET request to /api/v1/getLog endpoint took 131.96009999513626 milliseconds
[2021-09-13T07:57:54.029Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
[2021-09-13T07:57:54.033Z] Executing Sending GET request to /api/v1/getLog endpoint took 267.3488999903202 milliseconds
[2021-09-13T07:57:54.033Z] Sending GET request to /api/v1/getLog endpoint resulted in an error: {}
Hi, I have two projects in one workspace "Project" and "Project - Test". I start the synchronization, everything is done and "Object IDs are now in sync with azure back end. Happy developing" is displayed.
But when I look at "AL OBJECT ID NINJA: RANGE EXLORER", I only find the scope for "Project - Test" and doesnt work.
Some idea?
When Ninja is configured to suggest object IDs per range (objectIdNinja.requestPerRange
configuration setting) and there are multiple ranges, then suggestions are not sorted correctly.
For example, ranges are configured like this:
[
{
"from": 50000,
"to": 99999,
},
{
"from": 2150500,
"to": 2150599
}
]
Ninja will suggest these IDs (in this order):
2150500
50000
Suggestions should be sorted like this:
50000
2150500
The sort order should not be numeric, but should follow the range order in app.json
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.