Having multiple optional segments in a NancyFX Route - nancy

I have the following route in NancyFX:
Get["/Foo/{A?}/{B?}/{C?}"] = request => { /* some stuff */ };
It responds to http://localhost:1234/Foo/ amd http://localhost:1234/Foo//1/2/3/ but not http://localhost:1234/Foo/1/ and http://localhost:1234/Foo/1/2/. Basically you have to include all or none of the optional segments.I know I could use multiple segments, but how can I make each segment individually optional, and only dependent on the preceding segments?

You can do it like this:
Get["/Foo/{A?}"] =
Get["/Foo/{A?}/{B?}"] =
Get["/Foo/{A?}/{B?}/{C?}"] = request => { /* some stuff */ };

Related

Is there a way to schedule a deletion of a file on Firebase Storage?

I'am trying to build a ReactJS app which allows users to upload and download some files. I already have Firebase storage upload and download functionality in my app. The thing is that I want to schedule a task which will delete a file in 10 minutes for example each time user uploads his file.
Any advice?
If you are looking for a reliable server-side solution for this, you can make use of a Scheduled Cloud Function.
Here is an implementation of a Node-based Cloud Function:
import * as admin from "firebase-admin";
import * as functions from "firebase-functions";
admin.initializeApp();
/**
* Scheduled Cloud Function that deletes files older than 10 minutes,
* checking every 5 minutes.
*
* Files must be prefixed with "tmpUserUploads" to be checked by this
* function. If a file has a temporary or event-based hold on it, it
* will be skipped over by this function.
*
* #author samthecodingman [MIT License]
* #see https://stackoverflow.com/a/67724030/3068190
*
* #example
* "tmpUserUploads/someFile.png" // -> checked
* "tmpUserUploads/users/someUserId/someFile.png" // -> checked
* "profilePictures/someUserId/profile#1x.png" // -> not checked
*/
export cleanupTemporaryFiles =
functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {
// variables for tracking statistics
let processedCount = 0, disposedCount = 0, skippedCount = 0, erroredCount = 0, totalCount = 0;
const errorCountsByCode = {};
try {
const bucket = admin.storage().bucket();
// Query for all files starting with "tmpUserUploads"
const [filesArray] = await bucket.getFiles({
prefix: "tmpUserUploads"
});
totalCount = filesArray.length;
// variables with our settings to be reused below
const TIMESTAMP_TEN_MINUTES_AGO = Date.now() - 600000;
const DELETE_OPTIONS = { ignoreNotFound: true };
// If this number is regularly large, consider shortening the interval above
console.log("Found ${totalCount} files that need to be checked.");
// Process purge of each file as applicable keeping track of the results
const deleteOldFileResults = await Promise.all(
filesArray.map(async (file) => {
let metadata;
try {
// get the metadata for this file object
[metadata] = await file.getMetadata();
// pull out the bits we need
const { temporaryHold, eventBasedHold, timeCreated } = metadata;
// held files should not be deleted (will throw an error if you try)
const activeHold = temporaryHold || eventBasedHold;
// dispose when not held and older than 10 minutes
const dispose = !activeHold && timeCreated < TIMESTAMP_TEN_MINUTES_AGO;
if (dispose) {
await file.delete(DELETE_OPTIONS);
disposedCount++;
} else if (activeHold) {
skippedCount++;
}
processedCount++;
return { file, metadata, disposed: dispose, skipped: activeHold };
} catch (error) {
// trap the error so other files still attempt to be deleted
erroredCount++;
processedCount++;
const code = deleteResult.error.code || "unknown";
const errorCountForCode = (errorsByCode[code] || 0) + 1;
// Consider crashing function if same error code is encountered many times
// if (errorCountForCode > 10) {
// throw new Error(`Error code "${code}" has been encountered more than 10 times`);
// }
errorCountsByCode[code] = errorCountForCode;
return { file, metadata, disposed: false, skipped: true, error };
}
})
);
// Assemble an informative log message
const skippedLogMessage = skippedCount === 0
? "No files had active holds"
: `${skippedCount} of these were skipped due to active holds`;
const errorLogMessage = erroredCount === 0
? "no errors were encountered"
: `${erroredCount} were skipped due to errors (Error code breakdown: ${JSON.stringify(errorCountsByCode)})`;
console.log(`${disposedCount}/${totalCount} temporary files were purged. ${skippedLogMessage} and ${errorLogMessage}.`);
} catch (error) {
const stats = JSON.stringify({
disposed: disposedCount,
skipped: skippedCount,
errored: erroredCount,
errorCodeCounts: errorCountsByCode
});
console.error(`Critical failure: ${error.message}. Encounted after processing ${processedCount}/${totalCount} files: ${stats}`);
}
})
Nothing is built into Firebase for this, but Cloud Storage (the underlying storage mechanism) has something known as object lifecycle management, with which:
you can assign a lifecycle management configuration to a bucket. The configuration contains a set of rules which apply to current and future objects in the bucket. When an object meets the criteria of one of the rules, Cloud Storage automatically performs a specified action on the object.
If the deletion rules are really as constant as you say, that's where I'd look.
If the rules are more complex, I'd typically start with Cloud Functions as there I can write code that run periodically to do the cleanup.

How to get the read data from a vr_ad_sequence

I have a register read sequence that goes something like this:
extend vr_ad_sequence_kind: [READ_REG];
extend READ_REG vr_ad_sequence {
// register to read
reg_kind : vr_ad_reg_kind;
!reg : vr_ad_reg;
// more fields no longer shown here
body() #driver.clock is {
var reg_item : vr_ad_reg; // reg_item gets a value from a
// method that returns the correct
// register instance from the addr_map,
// which I no longer want to show here
reg = new vr_ad_reg with { .kind = reg_kind; };
read_reg { .static_item == reg_item; } reg;
};
};
Now, I have a virtual sequence that does the vr_ad_sequence above:
extend MAIN MAIN_TEST sample_vseq {
!reg_read : READ_REG vr_ad_sequence;
body() #driver.clock is first {
do reg_read keeping {
.driver == driver.reg_driver;
.reg_kind == MY_REGISTER;
};
// how to get the value of MY_REGISTER.MY_FIELD from
// the reg_read sequence above?
};
};
My main objective is to read the value of a specific register bit field which is MY_FIELD in the above example. Is there a way to do it without modifying anything in the original READ_REG vr_ad_sequence? If it can't be helped, how do I make the READ_REG vr_ad_sequence return the read value to the calling sample_vseq?
Thanks very much in advance.
To obtain the register value after the read you first must make sure that the read is finished on the bus. So either your BFM is blocking (which often it isn't) or you add a flag to the sequence that tells whether the response has been received (this can be set from the BFM/driver).
Next, you can get the value from the vr_ad_map instance.
E.g.
body() #driver.clock is first {
do reg_read keeping {
.driver == driver.reg_driver;
.reg_kind == MY_REGISTER;
};
// Wait for read response
sync true(reg_read != NULL and reg_read.done);
// Access shadow register through pointer to vr_ad_map instance
print addr_map.get_register_by_kind(MY_REGISTER).as_a(MY_REGISTER vr_ad_reg).MY_FIELD;
};
(I can't check the syntax right now)

How to use html webworkers with angularjs?

I am handling very hight dataset with type arry. While iterating through this arrays my application gets performance hit. I want to use webworkers which will perform manipulation operations on huge array and it will directly return the processed dataset back to application.web
Take a look at https://github.com/vkiryukhin/ng-vkthread I develop it exactly for such kind of tasks. It let you easily export function in a thread, execute it and get result in UI. Even more: you can download data directly in a thread rather than transfer it from UI to a thread.
the very basic usage is:
/* function to execute in a thread */
function foo(n, m){
return n + m;
}
/* create an object, which you pass to vkThread as an argument*/
var param = {
fn: foo // <-- function to execute
args: [1, 2] // <-- arguments for this function
};
/* run thread */
vkThread.exec(param).then(
function (data) {
console.log(data); // <-- thread returns 3
},
function(err) {
alert(err); // <-- thread returns error message
}
);
Doc and examples: http://www.eslinstructor.net/ng-vkthread/demo/

symfony2 routing, optional prefix from database

Basically what i want to achieve is this:
I have this paths:
http://SITENAME/dashboard
http://SITENAME/users
And they are mapped to the right controllers and actions:
/**
* #Route("/dashboard")
*/
public function dashboardAction()
{
// handle the request
}
/**
* #Route("/users")
*/
public function usersAction()
{
// handle the request
}
Now I want to make these other paths to map to the same controllers and actions:
http://SITENAME/{companyName}/dashboard
http://SITENAME/{companyName}/users
companyName is a name that I check on db if exists and if not throw a NotFound Exception.
These paths will just add some filter to the queries made, basically showing the same data structure.
I know I can create other actions and put those after the previous ones in order to be catched but I'm asking if there's something clever... something like this:
/**
* #Route("/({companyName}/)dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}
where companyName is optional.
Thanks...
UPDATE
As Manolo suggested I already tried something like this and it works:
/**
* #Route("/dashboard")
* #Route("/{companyName}/dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}
But I think there's a clever way of handling it...
Look at this example: http://symfony.com/doc/current/book/routing.html#routing-with-placeholders
// src/AppBundle/Controller/BlogController.php
// ...
/**
* #Route("/blog/{page}", defaults={"page" = 1})
*/
public function indexAction($page)
{
// ...
}
When page is not defined in the route, it is equal to 1.
But this won't work in your case, because you defined two routes for the same action:
/dasboard
/{companyName}/dashboard
So you have two options:
1. Define two routes for the same action (weird).
2. Change your defined route to: /dashboard/{companyName} (better)
Then, you can get /dashboard and /dashboard/{companyName} with the same action.
Try like this:
/**
* #Route("/{companyName}/dashboard")
*/
public function dashboardAction($companyName = null)
{
// handle the request
}
I suggest you to use the #ParamConverter annotation calls converters to convert request parameters to objects.
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
/**
* #Route("/dashboard")
* #Route("/({companyName}/)dashboard")
* #ParamConverter("company", class="AcmeDemoBundle:Company", options={"name" = "companyName"})
*/
public function showAction(Company $company = null)
{
}
The double route definition permit the default null company value
Hope this help

Angular Translate - how to retrieve dynamic variable list

I have this in the translation json file:
{
"test_key" : "Var1: {{var1}} Var2: {{var2}} Var3: {{var3}}"
}
For this to work, I need to provide var1, var2, and var 3. For example:
$translate('test_key', { var1: 1, var2: 2, var3: 3 });
The issue now is that var1, var2, var3 could be any dynamic variables. What I need now is to get all the list of dynamic variables so I can provide whatever values it may need.
Ideally, this is the goal I am trying to achieve (pseudo code)
var dynamicVars = getDynamicVarList(); // I need this, but how?
dynamicVars.forEach(function (key) {
switch (key) {
case "var1":
return 1;
case "var2":
return 2;
case "var3":
return 3;
default:
return null;
}
});
If it is Pascal Precht translate, then you set JSON file in module options, before application init. It's rather not possible with standard mechanisms. It offer JSON, but when it is loaded, then it's hard to change something, without changing source code of angular translate module.
If the reason you want this is to have many languages, then you can set many languages codes in $translate.
Another solution is to load JSON from server, which performs operations on var1, var2, var3 and hence returns static json, but you can do $http calls with commands to change variables in switch statement.
It looks somehow linguistic approach, Java is good for this. Grails may be fine framework for returning REST services.
Again, to restate the problem, the issue is that you do not know ahead of time which dynamic variables are to be used.
I solved the issue by using a customer interpolator.
So when you do
{{'testkey'|translate}}
and your lang.json has:
"testkey" :"this is number {{variable1}}"
It will get resolved to
this is number 1
Code:
app.factory('customTranslateInterpolator',
["$interpolate",
function ($interpolate) {
var $locale;
var customTranslateInterpolator = {};
/**
* This will be your custom dynamic vars resolution method
*/
var resolveExpressions = function (expressions) {
var values = {};
expressions.forEach(function (key) {
values[key] = resolveVariable(key);
});
return values;
}
/**
* The actual method for key:value mapping
*/
var resolveVariable = function(key) {
var retVal;
switch (key) {
case "variable1":
retVal = 1;
break;
default:
retVal = "";
}
return retVal;
}
customTranslateInterpolator.setLocale = function (locale) {
$locale = locale;
}
customTranslateInterpolator.getInterpolationIdentifier = function () {
return 'custom';
},
/**
* Custom interpolate
* interpolateParams will overwrite resolve expressions. This will allow developers
* to pass values to the translate directives or by using $translate service.
*
* #param {string} string the string retrieved from the language json file
* #param {object} interpolateParams the {key:value} object passed to the angular-translate features.
*/
customTranslateInterpolator.interpolate = function (string, interpolateParams) {
var result;
interpolateParams = interpolateParams || {
};
// Retrieve expressions and resolve them
var interpolatedString = $interpolate(string);
var resolvedExpressions = resolveExpressions(interpolatedString.expressions);
// Merge interpolateParams onto resolvedExpressions so that interpolateParams overwrites resolvedExpressions
angular.extend(resolvedExpressions, interpolateParams);
result = interpolatedString(resolvedExpressions);
return result;
}
return customTranslateInterpolator;
}]);
make sure you let angular-translate know you are using a custom interpolator
$translateProvider.useInterpolation('customTranslateInterpolator');
Note that you can still provide your own translate-values, and this will override whatever you have in resolveVariable()
So if you do
{{'testkey' | translate:"{variable1:'2'}"}}
It will resolve to
this is number 2
Hope this helps others.
-Lucky M.

Resources