问:
Codable class does not conform to protocol Decodable
Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message?

```<code>class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}
</code>```

I do not wish to save the publication var since the Publication owns the Bookmark but the bookmark needs to know which Publication it belongs to. The decode init of Publication will set the bookmark reference to itself.

答:
Simply because your CodingKeys enum is not exhaustive, add publication property to the enum to achieve that.

try this:

```<code>class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   // All your properties should be included
   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
      case publication   // this one was missing
   }
}
</code>```

You wont need the init method anymore as the implementation now can be synthesized.

Body:
Why am I getting a "Type 'Bookmark' does not conform to protocol 'Decodable'" error message?

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
   }

   init(publication: Publication?, indexPath: [Int]) {
      self.publication = publication
      self.indexPath = indexPath
   }
}

I do not wish to save the publication var since the Publication owns the Bookmark but the bookmark needs to know which Publication it belongs to. The decode init of Publication will set the bookmark reference to itself.

Body:
Simply because your CodingKeys enum is not exhaustive, add publication property to the enum to achieve that.

try this:

class Bookmark: Codable {
   weak var publication: Publication?
   var indexPath: [Int]
   var locationInText = 0

   // All your properties should be included
   enum CodingKeys: String, CodingKey {
      case indexPath
      case locationInText
      case publication   // this one was missing
   }
}

You wont need the init method anymore as the implementation now can be synthesized.


来源: stackexchange

问:
How can I do face recognition of two images using opencv java in android
I'm trying to create a face recognition application in android studio in java language. I spent considerable amount of time, searching for step by step guides for achieving this function. I found many tutorials for python language and i couldn't find any proper tutorial or atleast a video tutorial for java.

Can someone please provide me with a proper link with the steps to do face recognition with OpenCv in android using java language.
I'm new to OpenCv, so i have no big idea on its functions.

Your help is highly appreciated

Update 1 ::
I'm trying to capture the image of the user and then cross check the taken image with an image that is already available in the gallery.
I want to know if both are the same so that i can allow the user to use the application.

答:
I actually made a Java program that utilised OpenCV for facial recognition earlier this year.
For me it was an utter nightmare. Guides to doing this on Java are basically nonexistent and the documentation for Java OpenCV is very poor.

What I ended up doing to get to grips with OpenCV was I used PyImageSearch to learn how OpenCV works and then just trawled through the OpenCV javadocs until I found the most similar classes to what was being used in PyImageSearch.

There are a few guides for OpenCV recognition using Java (I'll have a look through my notes when I get a chance and see if I saved any links for my own reference) but none of them were for what I needed.

If you edit your post with some more information on the recognition you're trying to do (video or jpeg or png?; frontal faces or side faces?; specific faces or faces in general?) I may be able to help a little more.

The Youtube link that @Varma posted might help you get to grips with OpenCV as a whole, but that series doesn't seem to cover facial recognition.

EDIT #1

Okay, recognising who someone is via an image is definitely doable with OpenCV, but it's not something I've done. Here's a PyImageSearch page on how to do it in Python. The methodology for doing it in Java with OpenCV will most likely be more or less the same even thought the syntax will - of course - make it look very different (should mostly be a matter of finding the equivalent Java classes and methods).

If it proves difficult, there are alternatives to OpenCV you could use, like these or Google's API. Keep in mind though that facial recognition is not very secure and does come with some controversy.

ContentLicense: CC BY-SA 4.0


问:
How to replace www from the url in ruby?
I want to replace www from this url "https://www.cmnetwork.co/courses/3684/redirect"
with newlife.

I know using split we can do this. Is there any standard way of doing this?

Newly generated url should be:
"https://newlife.cmnetwork.co/courses/3684/redirect"

答:
try the following code to replace www from url eg.

```<code>url = "www.google.com"
url.gsub!('www.', 'app.')
</code>```

Body:
try the following code to replace www from url eg.

url = "www.google.com"
url.gsub!('www.', 'app.')


问:
Why do some images get stretched when drawing them with e.Graphics.DrawImage
I want to create a rotating wheel in c# form and some pictures get stretched for no apparent reason.

I tried looking into file properties as some images get stretched and some are just fine but i failed to find anything.

```<code>private void Form1_Paint(object sender, PaintEventArgs e)
        {
            angle = (int)(angle * szybkosc);
            //
            //kolo1
            Bitmap bit_kolo1 = new Bitmap(kolo1.Width, kolo1.Height);
            Graphics gkolo1 = Graphics.FromImage(bit_kolo1);
            gkolo1.TranslateTransform(bit_kolo1.Width / 2, bit_kolo1.Height / 2);
            gkolo1.RotateTransform(angle);
            gkolo1.TranslateTransform(-bit_kolo1.Width / 2, -bit_kolo1.Height / 2);
            gkolo1.InterpolationMode = InterpolationMode.HighQualityBicubic;

            gkolo1.DrawImage(kolo1, 0,0);
</code>```

EDIT 1: I noticed that is only happenes with pictures that i previously cropped using gimp. Still dont know how to fix it tho

答:
When using Graphics.DrawImage do always specify the exact size because in some cases the image will be stretched/shrunken otherwise:

```<code>gkolo1.DrawImage(kolo1, 0, 0, kolo1.Width, kolo1.Height); // or whatever desired size
</code>```

If you don't specify the size the default behavior considers the HorizontalResolution and VerticalResolution properties, which are arbitrary values in DPI and it seems Gimp does not adjust these values accurately when you crop the image so it will be stretched (to the original size maybe?).

Body:
I want to create a rotating wheel in c# form and some pictures get stretched for no apparent reason.

I tried looking into file properties as some images get stretched and some are just fine but i failed to find anything.

private void Form1_Paint(object sender, PaintEventArgs e)
        {
            angle = (int)(angle * szybkosc);
            //
            //kolo1
            Bitmap bit_kolo1 = new Bitmap(kolo1.Width, kolo1.Height);
            Graphics gkolo1 = Graphics.FromImage(bit_kolo1);
            gkolo1.TranslateTransform(bit_kolo1.Width / 2, bit_kolo1.Height / 2);
            gkolo1.RotateTransform(angle);
            gkolo1.TranslateTransform(-bit_kolo1.Width / 2, -bit_kolo1.Height / 2);
            gkolo1.InterpolationMode = InterpolationMode.HighQualityBicubic;

            gkolo1.DrawImage(kolo1, 0,0);

EDIT 1: I noticed that is only happenes with pictures that i previously cropped using gimp. Still dont know how to fix it tho

Body:
When using Graphics.DrawImage do always specify the exact size because in some cases the image will be stretched/shrunken otherwise:

gkolo1.DrawImage(kolo1, 0, 0, kolo1.Width, kolo1.Height); // or whatever desired size

If you don't specify the size the default behavior considers the HorizontalResolution and VerticalResolution properties, which are arbitrary values in DPI and it seems Gimp does not adjust these values accurately when you crop the image so it will be stretched (to the original size maybe?).


问:
Syntax error or access violation: 1064 You have an error in your SQL syntax in alter table
I am trying to alter the auto_increment by laravel stament function and it is giving the error.

The complete error message displaying is SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1 (SQL: alter table bills AUTO_INCREMENT=9)

```<code>if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=?',array('invoice_no'=>$invoice_no));
    dd(DB::getQueryLog());
    //return "<script>alert('Quantity is not available for product ".$item_name[$i]."');location.href='/create';</script>";
}
</code>```

答:
You can write the laravel query in two diffrent way you can tokenize variable

1) First method

```<code>if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=:invoice_no',array('invoice_no'=>$invoice_no));
    dd(DB::getQueryLog());
    //return "<script>alert('Quantity is not available for product ".$item_name[$i]."');location.href='/create';</script>";
}
</code>```

2) Second method

```<code>if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=?',[$invoice_no]);
    dd(DB::getQueryLog());
    //return "<script>alert('Quantity is not available for product ".$item_name[$i]."');location.href='/create';</script>";
}
</code>```

You can also write query below but your query will be wide open for sql injection.

DB::statement('alter tablebillsAUTO_INCREMENT = '.$invoice_no);

Body:
I am trying to alter the auto_increment by laravel stament function and it is giving the error.

The complete error message displaying is SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?' at line 1 (SQL: alter table bills AUTO_INCREMENT=9)

if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=?',array('invoice_no'=>$invoice_no));
    dd(DB::getQueryLog());
    //return "";
}

Body:
You can write the laravel query in two diffrent way you can tokenize variable

1) First method

if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=:invoice_no',array('invoice_no'=>$invoice_no));
    dd(DB::getQueryLog());
    //return "<script>alert('Quantity is not available for product ".$item_name[$i]."');location.href='/create';</script>";
}

2) Second method

if($quantity[$i]>$qtny)
{
    Bills::where('id','=',$invoice_no)->delete();
    DB::enableQueryLog();
        DB::statement('alter table `bills` AUTO_INCREMENT=?',[$invoice_no]);
    dd(DB::getQueryLog());
    //return "<script>alert('Quantity is not available for product ".$item_name[$i]."');location.href='/create';</script>";
}

You can also write query below but your query will be wide open for sql injection.

DB::statement('alter tablebillsAUTO_INCREMENT = '.$invoice_no);


问:
How to implement Google Play In-App Update and use Play Core Library with Xamarin
Google provides a new way to implement in-app update : https://developer.android.com/guide/app-bundle/in-app-updates that can be used to force users to update their app with the latest version available.

To be able to use this new feature, it requires the use of Play Core Library 1.5.0 or higher : https://developer.android.com/guide/app-bundle/playcore

It is possible to use it from Xamarin and to implement in-app update with this new capability ?

Regards

答:
UPDATE: CHECK https://github.com/PatGet/XamarinPlayCoreUpdater

I was able to come up with the Xamarin binding for the play core library which can be found on my drive here

Will be packaging it to NuGet soon, will update here once I do


问:
change color of ion range-slider handle
If I try to change the default color of ion range-slider (available here: https://github.com/IonDen/ion.rangeSlider) from red (default) to blue, like that:

```<code>.irs-slider.single {
    background: blue;
}
</code>```

It becomes square:

(originally it looks like a thin red line: )

What am I doing wrong?

DEMO

https://jsfiddle.net/chapkovski/xpvt214o/995048/

$(".js-range-slider").ionRangeSlider({
        type: "single",
        min: 0,
        max: 1000,
        from: 200,
        to: 500,
        grid: true
    });```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.irs-slider.single {
    background: blue;
}</code>```

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.2.0/css/ion.rangeSlider.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.2.0/css/ion.rangeSlider.skinFlat.css">
<input type="text" class="js-range-slider" name="my_range" value="" />```

答:
Below snippet for change whole ion range slider color to any color

$(".js-range-slider").ionRangeSlider({
  type: "single",
  min: 0,
  max: 1000,
  from: 200,
  to: 500,
  grid: true
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>    .irs--flat .irs-handle>i:first-child {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-bar {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-from, .irs--flat .irs-to, .irs--flat .irs-single {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-from:before, .irs--flat .irs-to:before, .irs--flat .irs-single:before {
    border-top-color: #4e73df!important;//Replace With Your color code
}</code>```

   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/css/ion.rangeSlider.min.css"/>

<input type="text" class="js-range-slider" name="my_range" value="" />```

Title: change color of ion range-slider handle

Body:
If I try to change the default color of ion range-slider (available here: https://github.com/IonDen/ion.rangeSlider) from red (default) to blue, like that:

.irs-slider.single {
    background: blue;
}

It becomes square:

(originally it looks like a thin red line: )

What am I doing wrong?

DEMO

https://jsfiddle.net/chapkovski/xpvt214o/995048/

$(".js-range-slider").ionRangeSlider({
        type: "single",
        min: 0,
        max: 1000,
        from: 200,
        to: 500,
        grid: true
    });

.irs-slider.single {
    background: blue;
}

<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.2.0/css/ion.rangeSlider.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.2.0/css/ion.rangeSlider.skinFlat.css">
<input type="text" class="js-range-slider" name="my_range" value="" />

Body:
Below snippet for change whole ion range slider color to any color

$(".js-range-slider").ionRangeSlider({
  type: "single",
  min: 0,
  max: 1000,
  from: 200,
  to: 500,
  grid: true
});

    .irs--flat .irs-handle>i:first-child {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-bar {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-from, .irs--flat .irs-to, .irs--flat .irs-single {
    background-color: #4e73df!important;//Replace With Your color code
}
.irs--flat .irs-from:before, .irs--flat .irs-to:before, .irs--flat .irs-single:before {
    border-top-color: #4e73df!important;//Replace With Your color code
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/css/ion.rangeSlider.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/js/ion.rangeSlider.min.js"></script>
<input type="text" class="js-range-slider" name="my_range" value="" />


问:
SSH to Google Compute instance using NodeJS, without gcloud
I'm trying to create a SSH tunnel into a compute instance, from an environment that doesn't have gcloud installed (App Engine Standard NodeJS Environment).

What are the steps needed to do that? How does gcloud compute ssh command does it? Is there a NodeJS library that already does it?

答:
I created the package gcloud-ssh-tunnel that does the necessary steps:

Create a private/public key using sshpk

Imports the public key using the OS Login API

SSH using ssh2 (and specifically create a tunnel, because this was the use case I needed - see the Why? section in the package)

Delete the public key using the OS Login API (to not overflow the account or leave security access)


问:
Load Geofirestore documents results into RecyclerView
I use GeoFirestore to find the nearest location, it worked but I need to load the documents that I got into RecyclerView, how can possibly achieve that?

GeoFirestore method

```<code>   private void getNearestEstate(){

    GeoQuery geoQuery = geoFirestore.queryAtLocation(new GeoPoint(latitude, longitude), 2);
    geoQuery.addGeoQueryDataEventListener(new GeoQueryDataEventListener() {
        @Override
        public void onDocumentEntered(DocumentSnapshot documentSnapshot, GeoPoint geoPoint) {

        }
}
</code>```

load into Rv

```<code>   private void dataFetch(Query query,int rvView){

          FirestoreRecyclerOptions<Property> options = new FirestoreRecyclerOptions.Builder<Property>()
            .setQuery(query, Property.class)
            .build();

        Toast.makeText(getContext(),options.toString(),Toast.LENGTH_LONG).show();
    mAdapter = new DiscoverAdapter(options);
    RecyclerView recyclerView = root.findViewById(rvView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.HORIZONTAL,false));
    recyclerView.setAdapter(mAdapter);
    mAdapter.startListening();
    }
</code>```

答:
When you perform a GeoQuery against a Cloud Firestore database and use addGeoQueryDataEventListener(), there are a few methods that must be implemented. As in your example, one of those methods is called onDocumentEntered(). As you can see, it has two arguments, the first one being of type DocumentSnapshot. This object contains all the locations objects in your range. In order to be able to display those locations, you need to iterate through the DocumentSnapshot object and get all locations.

To display all the locations in a RecyclerView, you first need to create a list of locations. So when you iterate, add all location objects to a list. Then simply create an adapter and pass that list to it's constructor. Set the adapter to the RecyclerView and you are done.

If you thought you can pass the GeoQuery to a FirestoreRecyclerOptions object, as you normally do when querying a Cloud Firestore database, please note that this is not possible, since GeoQuery class does not extend com.google.firebase.firestore.Query.

Body:
I use GeoFirestore to find the nearest location, it worked but I need to load the documents that I got into RecyclerView, how can possibly achieve that?

GeoFirestore method

   private void getNearestEstate(){

    GeoQuery geoQuery = geoFirestore.queryAtLocation(new GeoPoint(latitude, longitude), 2);
    geoQuery.addGeoQueryDataEventListener(new GeoQueryDataEventListener() {
        @Override
        public void onDocumentEntered(DocumentSnapshot documentSnapshot, GeoPoint geoPoint) {

        }
}

load into Rv

   private void dataFetch(Query query,int rvView){

          FirestoreRecyclerOptions<Property> options = new FirestoreRecyclerOptions.Builder<Property>()
            .setQuery(query, Property.class)
            .build();

        Toast.makeText(getContext(),options.toString(),Toast.LENGTH_LONG).show();
    mAdapter = new DiscoverAdapter(options);
    RecyclerView recyclerView = root.findViewById(rvView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext(),LinearLayoutManager.HORIZONTAL,false));
    recyclerView.setAdapter(mAdapter);
    mAdapter.startListening();
    }


问:
Where the templ files are created in blob triggered azure function?
I am working on an Azure Function application on Windows Azure.
I have created a Blob triggered azure function that creats a file in temp folder. To get the path of temporary folder to create the temporary file I am using following code block:

```<code>string TempFolderLocation = Path.GetTempPath();
string TempFileName = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff") + ".txt";
string TempFilePath = Path.Combine(TempFolderLocation, TempFileName);
System.IO.File.WriteAllText(TempFilePath, "This is the time log : " + DateTime.UtcNow.ToString("yyyy.MM.dd HH:mm:ss.fff"));
</code>```

I get the path "D:\local\Temp\" as result of Path.GetTempPath().

I am not getting any error when above code gates executed But when I take KUDU of my azure function application, there is no files created in folder "D:\local\Temp\".

So my questions are:

Is execution of blob triggered azure function happening at different
location then KUDU?

Is the execution time temp folder is different then the actual?

Where can I see those temp files?

答:
The azure function doesn't share the temp storage with kudu (and there is a legacy flag to force them to share).

Check "Temporary files" section here:
https://github.com/projectkudu/kudu/wiki/Understanding-the-Azure-App-Service-file-system#temporary-files

Another important note is that the Main site and the scm site do not
  share temp files. So if you write some files there from your site, you
  will not see them from Kudu Console (and vice versa). You can make
  them use the same temp space if you disable separation (via
  WEBSITE_DISABLE_SCM_SEPARATION). But note that this is a legacy flag,
  and its use is not recommended/supported.

Body:
I am working on an Azure Function application on Windows Azure.
I have created a Blob triggered azure function that creats a file in temp folder. To get the path of temporary folder to create the temporary file I am using following code block:

string TempFolderLocation = Path.GetTempPath();
string TempFileName = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff") + ".txt";
string TempFilePath = Path.Combine(TempFolderLocation, TempFileName);
System.IO.File.WriteAllText(TempFilePath, "This is the time log : " + DateTime.UtcNow.ToString("yyyy.MM.dd HH:mm:ss.fff"));

I get the path "D:\local\Temp\" as result of Path.GetTempPath().

I am not getting any error when above code gates executed But when I take KUDU of my azure function application, there is no files created in folder "D:\local\Temp\".

So my questions are:

Is execution of blob triggered azure function happening at different
location then KUDU?

Is the execution time temp folder is different then the actual?

Where can I see those temp files?


问:
nhibernate collection set mapping to avoid n+1 select and duplicate rows with fetch join
I have a object table and object aliases table.

The aliases is just a set collection of strings:

```<code>object.Aliases
</code>```

If I map the collection like this:

```<code><class name="Object" table="Object" lazy="false">
    ...
    properties...
    ...
    <set name="Aliases" table="Aliases" inverse="true" lazy="false" fetch="join" >
      <key column="ObjectId" />
      <element column="Name" type="String"/>
    </set>
    ...
</class>
</code>```

then

```<code>session.CreateCriteria(typeof (T)).List<T>();
</code>```

from base repository which fetches all objects, returns duplicates for each alias. Why? how can I get rid of the duplicate objects in the list?

Thank you all for your time.

EDIT:
Updated mappings... but that's all the mappings. Aliases doesn't have it's own class as it's just a set of strings that needs to be loaded into ISet<string> Object.Aliases

答:
For the select n+1 problem add batch-size="10" to your mappings

```<code><set name="Aliases" batch-size="10" ...
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a object table and object aliases table.

The aliases is just a set collection of strings:

object.Aliases

If I map the collection like this:

<class name="Object" table="Object" lazy="false">
    ...
    properties...
    ...
    <set name="Aliases" table="Aliases" inverse="true" lazy="false" fetch="join" >
      <key column="ObjectId" />
      <element column="Name" type="String"/>
    </set>
    ...
</class>

then

session.CreateCriteria(typeof (T)).List<T>();

from base repository which fetches all objects, returns duplicates for each alias. Why? how can I get rid of the duplicate objects in the list?

Thank you all for your time.

EDIT:
Updated mappings... but that's all the mappings. Aliases doesn't have it's own class as it's just a set of strings that needs to be loaded into ISet<string> Object.Aliases

Body:
For the select n+1 problem add batch-size="10" to your mappings

<set name="Aliases" batch-size="10" ...


问:
Rails Ahoy datastore track_visit not persisting
I'm using Rails 4.1.5 and Ahoy. I've added an additional field to the Visit model called 'visitor_email' (with a migration). I can manually create a Visit object with a visitor_email.

In config/initializers/ahoy.rb, I'm subscribing to the track_visit data store.
Here, I want to add the user's email to the new Visit model. I can see that the attribute being add to the data hash before I call super. But I can also that it is never written to the DB.

```<code>class Ahoy::Store < Ahoy::Stores::ActiveRecordTokenStore
  # customize here

  def track_visit(data)
    # new visit

    # if the landing page has a param that indicates it came from the share_profile_mailer
    # if request.params[:landing_page] != request.params[:landing_page].split('?visiting_user=')
    #   data[:visitor_email] = request.params[:landing_page].split('?visiting_user=')[1]
    # end

    data[:visitor_email] = "example@email.com"
    super(data)
  end
end
</code>```

Watching the server, I see:

```<code>Processing by Ahoy::VisitsController#create as JSON
  Parameters: {"visit_token"=>"d869c631-7f3a-4057-9bc2-eaa9160e9247", "visitor_token"=>"ebe8068e-fef0-4c25-93fd-54fe9e9aac75", "platform"=>"Web", "landing_page"=>"http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com", "screen_width"=>1440, "screen_height"=>900, "visit"=>{"visit_token"=>"d869c631-7f3a-4057-9bc2-eaa9160e9247", "visitor_token"=>"ebe8068e-fef0-4c25-93fd-54fe9e9aac75", "landing_page"=>"http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com", "screen_height"=>900, "screen_width"=>1440}}

[7, 16] in /Users/colin/Dev/Rails/sponsorcircle/config/initializers/ahoy.rb
    7:     # if the landing page has a param that indicates it came from the share_profile_mailer
    8:     # if request.params[:landing_page] != request.params[:landing_page].split('?visiting_user=')
    9:     #   data[:visitor_email] = request.params[:landing_page].split('?visiting_user=')[1]
   10:     # end
   11:
   12:     data[:visitor_email] = "example@email.com"
   13:     byebug
=> 14:     super(data)
   15:   end
   16: end
(byebug) data
{:started_at=>Mon, 27 May 2019 12:05:55 UTC +00:00, :visitor_email=>"example@email.com"}
(byebug) c
  User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 312  ORDER BY "users"."id" ASC LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "visits" ("browser", "device_type", "ip", "landing_page", "os", "screen_height", "screen_width", "started_at", "user_agent", "user_id", "visit_token", "visitor_token") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id"  [["browser", "Chrome"], ["device_type", "Desktop"], ["ip", "127.0.0.1"], ["landing_page", "http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com"], ["os", "Mac OS X"], ["screen_height", 900], ["screen_width", 1440], ["started_at", "2019-05-27 12:05:55.071724"], ["user_agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"], ["user_id", 312], ["visit_token", "d869c631-7f3a-4057-9bc2-eaa9160e9247"], ["visitor_token", "ebe8068e-fef0-4c25-93fd-54fe9e9aac75"]]
   (0.2ms)  COMMIT
Completed 200 OK in 7834ms (Views: 0.2ms | ActiveRecord: 4.1ms)
</code>```

I initially thought this might have something to do with my param not being permitted by the Visit controller. However, I cannot set any Visit field in track_visit (I've tried eg setting browser and utm_medium)

Note: I have restarted the rails server

Am I misunderstanding something here? Or approaching this in the wrong way?

答: This issue turned out to relate to the version of the Ahoy gem that I was using. I upgraded to 2.2.0 (I think 2.X is enough), and everything worked as expected - see https://github.com/ankane/ahoy/blob/master/docs/Ahoy-2-Upgrade.md for more details</p>

Body:
I'm using Rails 4.1.5 and Ahoy. I've added an additional field to the Visit model called 'visitor_email' (with a migration). I can manually create a Visit object with a visitor_email.

In config/initializers/ahoy.rb, I'm subscribing to the track_visit data store.
Here, I want to add the user's email to the new Visit model. I can see that the attribute being add to the data hash before I call super. But I can also that it is never written to the DB.

class Ahoy::Store < Ahoy::Stores::ActiveRecordTokenStore
  # customize here

  def track_visit(data)
    # new visit

    # if the landing page has a param that indicates it came from the share_profile_mailer
    # if request.params[:landing_page] != request.params[:landing_page].split('?visiting_user=')
    #   data[:visitor_email] = request.params[:landing_page].split('?visiting_user=')[1]
    # end

    data[:visitor_email] = "example@email.com"
    super(data)
  end
end

Watching the server, I see:

Processing by Ahoy::VisitsController#create as JSON
  Parameters: {"visit_token"=>"d869c631-7f3a-4057-9bc2-eaa9160e9247", "visitor_token"=>"ebe8068e-fef0-4c25-93fd-54fe9e9aac75", "platform"=>"Web", "landing_page"=>"http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com", "screen_width"=>1440, "screen_height"=>900, "visit"=>{"visit_token"=>"d869c631-7f3a-4057-9bc2-eaa9160e9247", "visitor_token"=>"ebe8068e-fef0-4c25-93fd-54fe9e9aac75", "landing_page"=>"http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com", "screen_height"=>900, "screen_width"=>1440}}

[7, 16] in /Users/colin/Dev/Rails/sponsorcircle/config/initializers/ahoy.rb
    7:     # if the landing page has a param that indicates it came from the share_profile_mailer
    8:     # if request.params[:landing_page] != request.params[:landing_page].split('?visiting_user=')
    9:     #   data[:visitor_email] = request.params[:landing_page].split('?visiting_user=')[1]
   10:     # end
   11:
   12:     data[:visitor_email] = "example@email.com"
   13:     byebug
=> 14:     super(data)
   15:   end
   16: end
(byebug) data
{:started_at=>Mon, 27 May 2019 12:05:55 UTC +00:00, :visitor_email=>"example@email.com"}
(byebug) c
  User Load (0.5ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 312  ORDER BY "users"."id" ASC LIMIT 1
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO "visits" ("browser", "device_type", "ip", "landing_page", "os", "screen_height", "screen_width", "started_at", "user_agent", "user_id", "visit_token", "visitor_token") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id"  [["browser", "Chrome"], ["device_type", "Desktop"], ["ip", "127.0.0.1"], ["landing_page", "http://localhost:3000/organizations/35?visiting_user=colindmccann@gmail.com"], ["os", "Mac OS X"], ["screen_height", 900], ["screen_width", 1440], ["started_at", "2019-05-27 12:05:55.071724"], ["user_agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"], ["user_id", 312], ["visit_token", "d869c631-7f3a-4057-9bc2-eaa9160e9247"], ["visitor_token", "ebe8068e-fef0-4c25-93fd-54fe9e9aac75"]]
   (0.2ms)  COMMIT
Completed 200 OK in 7834ms (Views: 0.2ms | ActiveRecord: 4.1ms)

I initially thought this might have something to do with my param not being permitted by the Visit controller. However, I cannot set any Visit field in track_visit (I've tried eg setting browser and utm_medium)

Note: I have restarted the rails server

Am I misunderstanding something here? Or approaching this in the wrong way?


问:
Multithreaded socket connection hangs c#. Socket timeout/hangs
I'm attempting to send print instructions to two printers over a socket connection. The script works fine then hangs and reports back:

System.IO.IOException: Unable to write data to the transport
  connection: A request to send or receive data was disallowed because
  the socket had already been shut down in that direction with a
  previous shutdown call

or

System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond
  after a period of time, or established connection failed because
  connected host has failed to respond

The issue is intermittent and I haven't been able to reproduce with a debugger attached.

Can anyone spot what could be causing this behavior? I've had issue with thread safety which I believe could be to blame.

Apologies for the amount of code. Due to the possibility of this being down to threading I've included as much scope as I can.

```<code>// main entry point
class HomeController{

    List<string> lsLabelResults = new List<string>("label result");
    PrinterBench pbBench        = new PrinterBench("192.168.2.20","192.168.2.21");

    void Process(){

        oPrintController = new PrintController(this);

        if(GetLabel()){
            // should always come out of the big printer (runs in background)
            oPrintController.PrintBySocketThreaded(lsLabelResults, pbBench.PostageLabelIP);
            // should always come out of the small printer
            oPrintController.PrintWarningLabel();
        }
    }
}

class PrintController{

    HomeController oHC;

    private static Dictionary<string, Socket> lSocks = new Dictionary<string, Socket>();

    private BackgroundWorker _backgroundWorker;
    static readonly object locker = new object();
    double dProgress;
    bool bPrintSuccess = true;

    public PrintController(HomeController oArg_HC)
    {
        oHC = oArg_HC;
    }

    public bool InitSocks()
    {
        // Ensure the IP's / endpoints of users printers are assigned
        if (!lSocks.ContainsKey(oHC.pbBench.PostageLabelIP))
        {
            lSocks.Add(oHC.pbBench.PostageLabelIP, null);
        }
        if (!lSocks.ContainsKey(oHC.pbBench.SmallLabelIP))
        {
            lSocks.Add(oHC.pbBench.SmallLabelIP, null);
        }

        // attempt to create a connection to each socket
        try
        {
            foreach (string sKey in lSocks.Keys.ToList())
            {
                if (lSocks[sKey] == null || !lSocks[sKey].Connected)
                {
                    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(sKey), 9100);
                    lSocks[sKey] = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    try
                    {

                        //lSocks[sKey].Connect(ep);
                        var result = lSocks[sKey].BeginConnect(ep, null, null);

                        bool success = result.AsyncWaitHandle.WaitOne(2000, true);
                        // dont need success
                        if (lSocks[sKey].Connected)
                        {
                            lSocks[sKey].EndConnect(result);
                        }
                        else
                        {
                            lSocks[sKey].Close();
                            throw new SocketException(10060); // Connection timed out.
                        }

                    }
                    catch(SocketException se)
                    {
                        if(se.ErrorCode == 10060)
                        {
                            oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                        }
                        else
                        {
                            oHC.WriteLog("Unable to init connection to printer. Error: " + se.ErrorCode.ToString(), Color.Red);
                        }
                    }
                    catch (Exception e)
                    {
                        oHC.WriteLog("Unable to init connection to printer. Error: " + e.ToString(), Color.Red);
                    }
                }
            }
        }catch (Exception e)
        {
            oHC.WriteLog(e.ToString(), true);
            return false;
        }

        return true;
    }

    public bool PrintBySocketThreaded(List<string> lsToPrint, string sIP)
    {
        // open both the sockets
        InitSocks();

        bBatchPrintSuccess = false;
        _backgroundWorker = new BackgroundWorker();

        _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        _backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        _backgroundWorker.WorkerReportsProgress = true;
        _backgroundWorker.WorkerSupportsCancellation = true;

        object[] parameters = new object[] { lsToPrint, sIP, lSocks };

        _backgroundWorker.RunWorkerAsync(parameters);
        return true;
    }

    // On worker thread, send to print!
    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        object[] parameters = e.Argument as object[];

        double dProgressChunks = (100 / ((List<string>)parameters[0]).Count);
        int iPos = 1;

        Dictionary<string, Socket> dctSocks = (Dictionary<string, Socket>)parameters[2];

        foreach (string sLabel in (List<string>)parameters[0] )
        {
            bool bPrinted = false;

            // thread lock print by socket to ensure its not accessed twice
            lock (locker)
            {
                // get relevant socket from main thread
                bPrinted = PrintBySocket(sLabel, (string)parameters[1], dctSocks[(string)parameters[1]]);
            }

            iPos++;
        }

        while (!((BackgroundWorker)sender).CancellationPending)
        {
            ((BackgroundWorker)sender).CancelAsync();
            ((BackgroundWorker)sender).Dispose();
            //Thread.Sleep(500);
        }
        return;
    }

    // Back on the 'UI' thread so we can update the progress bar (have access to main thread data)!
    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null) MessageBox.Show(e.Error.Message);
        if (bPrintSuccess) oHC.WriteLog("Printing Complete");

        bBatchPrintSuccess = true;

        ((BackgroundWorker)sender).CancelAsync();
        ((BackgroundWorker)sender).Dispose();
    }

    /// sends to printer via socket
    public bool PrintBySocket(string sArg_ToPrint, string sIP, Socket sock = null)
    {
        Socket sTmpSock = sock;

        if (sTmpSock == null)
        {
            InitSocks();

            if (!lSocks.ContainsKey(sIP))
            {
                throw new Exception("Sock not init");
            }
            else
            {
                sTmpSock = lSocks[sIP];
            }
        }

        try
        {

            if(!sTmpSock.Connected || !sTmpSock.IsBound)
            {
                InitSocks();

                if (!sTmpSock.Connected)
                {
                    oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                }
            }

            using (NetworkStream ns = new NetworkStream(sTmpSock))
            {
                byte[] toSend = null;

                // convert string to byte stream, or use byte stream
                if (byToPrint == null)
                {
                    toSend = Encoding.ASCII.GetBytes(sEOL + sArg_ToPrint);
                }
                else
                {
                    toSend = byToPrint;
                }

                ns.BeginWrite(toSend, 0, toSend.Length, OnWriteComplete, null);
                ns.Flush();
            }

            return true;

        }
        catch (Exception e)
        {
            oHC.WriteLog("Print by socket: " + e.ToString(), true);
            DisposeSocks();
        }
    }

    public bool PrintWarningLabel()
    {
        string sOut = sEOL + "N" + sEOL;
        sOut += "A0,150,0,4,3,3,N,\"WARNING MESSAGE TO PRINT\"" + sEOL;
        sOut += sEOL;

        if (PrintBySocket(sOut, oHC.pbBench.SmallLabelIP))
        {
            oHC.WriteLog("WARNING LABEL PRINTED");
            return true;
        }
        return false;
    }
}
</code>```

答:
It appears you’re connecting to TCP servers and sending some data. In modern .NET you don’t need explicit multithreading for that, async-await simplified things a lot. Here’s how I would probably do that.

```<code>static class NetworkPrinter
{
    const ushort tcpPort = 31337;
    const string sEOL = "\r\n";

    /// <summary>Send a single job to the printer.</summary>
    static async Task sendLabel( Stream stream, string what, CancellationToken ct )
    {
        byte[] toSend = Encoding.ASCII.GetBytes( sEOL + what );
        await stream.WriteAsync( toSend, 0, toSend.Length, ct );
        await stream.FlushAsync();
    }

    /// <summary>Connect to a network printer, send a batch of jobs reporting progress, disconnect.</summary>
    public static async Task printLabels( string ip, string[] labels, Action<double> progress, CancellationToken ct )
    {
        IPAddress address = IPAddress.Parse( ip );
        double progressMul = 1.0 / labels.Length;
        using( var tc = new TcpClient() )
        {
            await tc.ConnectAsync( address, tcpPort );
            Stream stream = tc.GetStream();
            for( int i = 0; i < labels.Length; )
            {
                ct.ThrowIfCancellationRequested();
                await sendLabel( stream, labels[ i ], ct );
                i++;
                progress( i * progressMul );
            }
        }
    }

    /// <summary>Send multiple batches to multiple printers, return true of all of them were good.</summary>
    public static async Task<bool> printBatches( LabelBatch[] batches )
    {
        await Task.WhenAll( batches.Select( a => a.print( CancellationToken.None ) ) );
        return batches.All( a => a.completed );
    }
}

/// <summary>A batch of labels to be printed by a single printer.</summary>
/// <remarks>Once printed, includes some status info.</remarks>
class LabelBatch
{
    readonly string ip;
    readonly string[] labels;
    public bool completed { get; private set; } = false;
    public Exception exception { get; private set; } = null;

    public LabelBatch( string ip, IEnumerable<string> labels )
    {
        this.ip = ip;
        this.labels = labels.ToArray();
    }

    /// <summary>Print all labels, ignoring the progress. This method doesn't throw, returns false if failed.</summary>
    public async Task<bool> print( CancellationToken ct )
    {
        completed = false;
        exception = null;
        try
        {
            await NetworkPrinter.printLabels( ip, labels, d => { }, ct );
            completed = true;
        }
        catch( Exception ex )
        {
            exception = ex;
        }
        return completed;
    }
}
</code>```

You might still need manual thread synchronization if you don’t have a synchronization context (e.g. you’re writing a console app) to report progress. You can get progress callbacks called in parallel from multiple printers. Progress reporting should be fast, a single lock() on a static object will do. Not required if you’re building a GUI app and calling printBatches from the GUI thread, the sync.context will serialize everything to the GUI thread, despite network requests will still run in parallel.

Body:
I'm attempting to send print instructions to two printers over a socket connection. The script works fine then hangs and reports back:

System.IO.IOException: Unable to write data to the transport
  connection: A request to send or receive data was disallowed because
  the socket had already been shut down in that direction with a
  previous shutdown call

or

System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond
  after a period of time, or established connection failed because
  connected host has failed to respond

The issue is intermittent and I haven't been able to reproduce with a debugger attached.

Can anyone spot what could be causing this behavior? I've had issue with thread safety which I believe could be to blame.

Apologies for the amount of code. Due to the possibility of this being down to threading I've included as much scope as I can.

// main entry point
class HomeController{

    List<string> lsLabelResults = new List<string>("label result");
    PrinterBench pbBench        = new PrinterBench("192.168.2.20","192.168.2.21");

    void Process(){

        oPrintController = new PrintController(this);

        if(GetLabel()){
            // should always come out of the big printer (runs in background)
            oPrintController.PrintBySocketThreaded(lsLabelResults, pbBench.PostageLabelIP);
            // should always come out of the small printer
            oPrintController.PrintWarningLabel();
        }
    }
}

class PrintController{

    HomeController oHC;

    private static Dictionary<string, Socket> lSocks = new Dictionary<string, Socket>();

    private BackgroundWorker _backgroundWorker;
    static readonly object locker = new object();
    double dProgress;
    bool bPrintSuccess = true;

    public PrintController(HomeController oArg_HC)
    {
        oHC = oArg_HC;
    }

    public bool InitSocks()
    {
        // Ensure the IP's / endpoints of users printers are assigned
        if (!lSocks.ContainsKey(oHC.pbBench.PostageLabelIP))
        {
            lSocks.Add(oHC.pbBench.PostageLabelIP, null);
        }
        if (!lSocks.ContainsKey(oHC.pbBench.SmallLabelIP))
        {
            lSocks.Add(oHC.pbBench.SmallLabelIP, null);
        }

        // attempt to create a connection to each socket
        try
        {
            foreach (string sKey in lSocks.Keys.ToList())
            {
                if (lSocks[sKey] == null || !lSocks[sKey].Connected)
                {
                    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(sKey), 9100);
                    lSocks[sKey] = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    try
                    {

                        //lSocks[sKey].Connect(ep);
                        var result = lSocks[sKey].BeginConnect(ep, null, null);

                        bool success = result.AsyncWaitHandle.WaitOne(2000, true);
                        // dont need success
                        if (lSocks[sKey].Connected)
                        {
                            lSocks[sKey].EndConnect(result);
                        }
                        else
                        {
                            lSocks[sKey].Close();
                            throw new SocketException(10060); // Connection timed out.
                        }

                    }
                    catch(SocketException se)
                    {
                        if(se.ErrorCode == 10060)
                        {
                            oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                        }
                        else
                        {
                            oHC.WriteLog("Unable to init connection to printer. Error: " + se.ErrorCode.ToString(), Color.Red);
                        }
                    }
                    catch (Exception e)
                    {
                        oHC.WriteLog("Unable to init connection to printer. Error: " + e.ToString(), Color.Red);
                    }
                }
            }
        }catch (Exception e)
        {
            oHC.WriteLog(e.ToString(), true);
            return false;
        }

        return true;
    }

    public bool PrintBySocketThreaded(List<string> lsToPrint, string sIP)
    {
        // open both the sockets
        InitSocks();

        bBatchPrintSuccess = false;
        _backgroundWorker = new BackgroundWorker();

        _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        _backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        _backgroundWorker.WorkerReportsProgress = true;
        _backgroundWorker.WorkerSupportsCancellation = true;

        object[] parameters = new object[] { lsToPrint, sIP, lSocks };

        _backgroundWorker.RunWorkerAsync(parameters);
        return true;
    }

    // On worker thread, send to print!
    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        object[] parameters = e.Argument as object[];

        double dProgressChunks = (100 / ((List<string>)parameters[0]).Count);
        int iPos = 1;

        Dictionary<string, Socket> dctSocks = (Dictionary<string, Socket>)parameters[2];

        foreach (string sLabel in (List<string>)parameters[0] )
        {
            bool bPrinted = false;

            // thread lock print by socket to ensure its not accessed twice
            lock (locker)
            {
                // get relevant socket from main thread
                bPrinted = PrintBySocket(sLabel, (string)parameters[1], dctSocks[(string)parameters[1]]);
            }

            iPos++;
        }

        while (!((BackgroundWorker)sender).CancellationPending)
        {
            ((BackgroundWorker)sender).CancelAsync();
            ((BackgroundWorker)sender).Dispose();
            //Thread.Sleep(500);
        }
        return;
    }

    // Back on the 'UI' thread so we can update the progress bar (have access to main thread data)!
    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null) MessageBox.Show(e.Error.Message);
        if (bPrintSuccess) oHC.WriteLog("Printing Complete");

        bBatchPrintSuccess = true;

        ((BackgroundWorker)sender).CancelAsync();
        ((BackgroundWorker)sender).Dispose();
    }

    /// sends to printer via socket
    public bool PrintBySocket(string sArg_ToPrint, string sIP, Socket sock = null)
    {
        Socket sTmpSock = sock;

        if (sTmpSock == null)
        {
            InitSocks();

            if (!lSocks.ContainsKey(sIP))
            {
                throw new Exception("Sock not init");
            }
            else
            {
                sTmpSock = lSocks[sIP];
            }
        }

        try
        {

            if(!sTmpSock.Connected || !sTmpSock.IsBound)
            {
                InitSocks();

                if (!sTmpSock.Connected)
                {
                    oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                }
            }

            using (NetworkStream ns = new NetworkStream(sTmpSock))
            {
                byte[] toSend = null;

                // convert string to byte stream, or use byte stream
                if (byToPrint == null)
                {
                    toSend = Encoding.ASCII.GetBytes(sEOL + sArg_ToPrint);
                }
                else
                {
                    toSend = byToPrint;
                }

                ns.BeginWrite(toSend, 0, toSend.Length, OnWriteComplete, null);
                ns.Flush();
            }

            return true;

        }
        catch (Exception e)
        {
            oHC.WriteLog("Print by socket: " + e.ToString(), true);
            DisposeSocks();
        }
    }

    public bool PrintWarningLabel()
    {
        string sOut = sEOL + "N" + sEOL;
        sOut += "A0,150,0,4,3,3,N,\"WARNING MESSAGE TO PRINT\"" + sEOL;
        sOut += sEOL;

        if (PrintBySocket(sOut, oHC.pbBench.SmallLabelIP))
        {
            oHC.WriteLog("WARNING LABEL PRINTED");
            return true;
        }
        return false;
    }
}

Body:
It appears you’re connecting to TCP servers and sending some data. In modern .NET you don’t need explicit multithreading for that, async-await simplified things a lot. Here’s how I would probably do that.

static class NetworkPrinter
{
    const ushort tcpPort = 31337;
    const string sEOL = "\r\n";

    /// <summary>Send a single job to the printer.</summary>
    static async Task sendLabel( Stream stream, string what, CancellationToken ct )
    {
        byte[] toSend = Encoding.ASCII.GetBytes( sEOL + what );
        await stream.WriteAsync( toSend, 0, toSend.Length, ct );
        await stream.FlushAsync();
    }

    /// <summary>Connect to a network printer, send a batch of jobs reporting progress, disconnect.</summary>
    public static async Task printLabels( string ip, string[] labels, Action<double> progress, CancellationToken ct )
    {
        IPAddress address = IPAddress.Parse( ip );
        double progressMul = 1.0 / labels.Length;
        using( var tc = new TcpClient() )
        {
            await tc.ConnectAsync( address, tcpPort );
            Stream stream = tc.GetStream();
            for( int i = 0; i < labels.Length; )
            {
                ct.ThrowIfCancellationRequested();
                await sendLabel( stream, labels[ i ], ct );
                i++;
                progress( i * progressMul );
            }
        }
    }

    /// <summary>Send multiple batches to multiple printers, return true of all of them were good.</summary>
    public static async Task<bool> printBatches( LabelBatch[] batches )
    {
        await Task.WhenAll( batches.Select( a => a.print( CancellationToken.None ) ) );
        return batches.All( a => a.completed );
    }
}

/// <summary>A batch of labels to be printed by a single printer.</summary>
/// <remarks>Once printed, includes some status info.</remarks>
class LabelBatch
{
    readonly string ip;
    readonly string[] labels;
    public bool completed { get; private set; } = false;
    public Exception exception { get; private set; } = null;

    public LabelBatch( string ip, IEnumerable<string> labels )
    {
        this.ip = ip;
        this.labels = labels.ToArray();
    }

    /// <summary>Print all labels, ignoring the progress. This method doesn't throw, returns false if failed.</summary>
    public async Task<bool> print( CancellationToken ct )
    {
        completed = false;
        exception = null;
        try
        {
            await NetworkPrinter.printLabels( ip, labels, d => { }, ct );
            completed = true;
        }
        catch( Exception ex )
        {
            exception = ex;
        }
        return completed;
    }
}

You might still need manual thread synchronization if you don’t have a synchronization context (e.g. you’re writing a console app) to report progress. You can get progress callbacks called in parallel from multiple printers. Progress reporting should be fast, a single lock() on a static object will do. Not required if you’re building a GUI app and calling printBatches from the GUI thread, the sync.context will serialize everything to the GUI thread, despite network requests will still run in parallel.


问:
Get count of array objects belonging to a partical ID in JavaScript/Node js
I have an array of arrays like this:

```<code>var array = [
    [ '2','Yes'],
    [ '2','Yes'],
    [ '2','Yes'],
    [ '3','Yes'],
    [ '3','Yes'],
    [ '4','Yes'],
]
</code>```

The ID's in the above array (2,3 and 4) come dynamically from a server response.
I need to count the number of entries for a particular ID.
I'm not able to figure out how to loop over this array to get the expected output.
The expected output is:

```<code>[{"ID" : "4", Count : "1"},{"ID" : "3", Count : "2"},{"ID" : "2",Count : "3"}]
</code>```

Note that the output is in the ascending order of the Count.

This is what I tried :

```<code>var temp1 = [];
                var temp2 = [];
                var temp3 = [];
                for(var i = 0; i < array.length; ++i){
                     if(array[i][0] == 2){
                        temp1.push(array[i])
                     }
                     if(array[i][0] == 1){
                        temp2.push(array[i])
                     }
                     if(array[i][0] == 3){
                        temp3.push(array[i])
                     }

                }

 var output = [{
                    ID: "2",
                    Count: temp1.length,
                },
                {
                    ID: "1",
                    Count: temp2.length,
                },
                {
                    ID: "3",
                    Count: temp3.length
                }]

console.log(output)
</code>```

I believe the way I'm doing it is not the best approach if the data is dynamic.
How do I do it in a better way?

答:
You could use map and filter to transform the array and count the ocurrences, then you sort the array by the count property:

const array = [
    [ '2','Yes'],
    [ '2','Yes'],
    [ '2','Yes'],
    [ '3','Yes'],
    [ '3','Yes'],
    [ '4','Yes'],
];

const result = [];
array.forEach( item => {
  if (result.find( id => item[0] === id["ID"])){
    return;
  }
  result.push({"ID": item[0], Count: array.filter(ids =>  ids[0] === item[0]).length});
})

// And then sort it
result.sort( (a,b) => a.Count - b.Count);

console.log(result);```

Body:
I have an array of arrays like this:

var array = [
    [ '2','Yes'],
    [ '2','Yes'],
    [ '2','Yes'],
    [ '3','Yes'],
    [ '3','Yes'],
    [ '4','Yes'],
]

The ID's in the above array (2,3 and 4) come dynamically from a server response.
I need to count the number of entries for a particular ID.
I'm not able to figure out how to loop over this array to get the expected output.
The expected output is:

[{"ID" : "4", Count : "1"},{"ID" : "3", Count : "2"},{"ID" : "2",Count : "3"}]

Note that the output is in the ascending order of the Count.

This is what I tried :

var temp1 = [];
                var temp2 = [];
                var temp3 = [];
                for(var i = 0; i < array.length; ++i){
                     if(array[i][0] == 2){
                        temp1.push(array[i])
                     }
                     if(array[i][0] == 1){
                        temp2.push(array[i])
                     }
                     if(array[i][0] == 3){
                        temp3.push(array[i])
                     }

                }

 var output = [{
                    ID: "2",
                    Count: temp1.length,
                },
                {
                    ID: "1",
                    Count: temp2.length,
                },
                {
                    ID: "3",
                    Count: temp3.length
                }]

console.log(output)

I believe the way I'm doing it is not the best approach if the data is dynamic.
How do I do it in a better way?


问:
Passing arbitrary number of parameters using vector in C++
I'm dealing with C++ objects that use destructor to deallocate resources. When passing those objects to a function with an arbitrary number of parameters.
Is there any way to get rid of using pointers in this case?

One possible solution is passing a vector of pointers to those objects.
if I pass the objects themselves, the destructors will be called twice, one is the real objects, another is when the vector is deallocated.

```<code>#include<iostream>
#include<vector>
class integer {
    private:
        int data;
    public:
        integer(int value = 0): data(value) {}
        ~integer() {}
        void increase() {
            data++;
        }
        friend std::ostream& operator<<(std::ostream& os, const integer& x);
};
std::ostream& operator<<(std::ostream& os, const integer& x) {
    os << x.data;
    return os;
}
void foo(std::vector<integer*> vec) {
    for (auto it = vec.begin(); it != vec.end(); it++) {
        (*it)->increase();
    }
}
int main() {
    integer x1(3);
    integer x2(4);
    integer x3(5);

    std::cout << x1 << " " << x2 << " " << x3 << std::endl;

    foo({&x1, &x2, &x3});

    std::cout << x1 << " " << x2 << " " << x3 << std::endl;

    return 0;
}
</code>```

Expected results:

```<code>3 4 5
4 5 6
</code>```

答:
You can use iterators. Once you have more than 3 you should not continue with x4 but use a containter anyhow. Your foo would be

```<code>template <typename iterator_t>
void foo(iterator_t begin,iterator_t end) {
    for ( ; begin != end; ++begin) begin->increase();
}
</code>```

And in main:

```<code>int main() {
    std::vector<integer> x { {3},{4},{5} };
    for (const auto& i : x) std::cout << i << " ";
    std::cout << "\n";

    foo(x.begin(),x.end());
    for (const auto& i : x) std::cout << i << " ";

    return 0;
}
</code>```

Body:
I'm dealing with C++ objects that use destructor to deallocate resources. When passing those objects to a function with an arbitrary number of parameters.
Is there any way to get rid of using pointers in this case?

One possible solution is passing a vector of pointers to those objects.
if I pass the objects themselves, the destructors will be called twice, one is the real objects, another is when the vector is deallocated.

#include<iostream>
#include<vector>
class integer {
    private:
        int data;
    public:
        integer(int value = 0): data(value) {}
        ~integer() {}
        void increase() {
            data++;
        }
        friend std::ostream& operator<<(std::ostream& os, const integer& x);
};
std::ostream& operator<<(std::ostream& os, const integer& x) {
    os << x.data;
    return os;
}
void foo(std::vector<integer*> vec) {
    for (auto it = vec.begin(); it != vec.end(); it++) {
        (*it)->increase();
    }
}
int main() {
    integer x1(3);
    integer x2(4);
    integer x3(5);

    std::cout << x1 << " " << x2 << " " << x3 << std::endl;

    foo({&x1, &x2, &x3});

    std::cout << x1 << " " << x2 << " " << x3 << std::endl;

    return 0;
}

Expected results:

3 4 5
4 5 6

Body:
You can use iterators. Once you have more than 3 you should not continue with x4 but use a containter anyhow. Your foo would be

template <typename iterator_t>
void foo(iterator_t begin,iterator_t end) {
    for ( ; begin != end; ++begin) begin->increase();
}

And in main:

int main() {
    std::vector<integer> x { {3},{4},{5} };
    for (const auto& i : x) std::cout << i << " ";
    std::cout << "\n";

    foo(x.begin(),x.end());
    for (const auto& i : x) std::cout << i << " ";

    return 0;
}


问:
Selecting Only The Latest Version Of A Field
I have a table schema with ID, Title, Date

and data looks something like this:

```<code>1  The title1    2011-04-05 00:00:00.000
2  Another title 2011-04-11 00:00:00.000
3  The title1    2011-04-11 16:49:23.633
4  The title1    2011-04-11 00:00:00.000
</code>```

I need help with sql to give me the latest date of each title.
So the output for the above data is

```<code>2  Another title 2011-04-11 00:00:00.000
3  The title1    2011-04-11 16:49:23.633
</code>```

答:
```<code>select mytable.Title, MAX(mytable.Date)
from mytable
group by mytable.Title
</code>```

Body:
I have a table schema with ID, Title, Date

and data looks something like this:

1  The title1    2011-04-05 00:00:00.000
2  Another title 2011-04-11 00:00:00.000
3  The title1    2011-04-11 16:49:23.633
4  The title1    2011-04-11 00:00:00.000

I need help with sql to give me the latest date of each title.
So the output for the above data is

2  Another title 2011-04-11 00:00:00.000
3  The title1    2011-04-11 16:49:23.633


问:
How to use document.onload Properly
I am currently learning window.onload and document.onload as attributes on html. But i fail to use them properly. In my code i want to focus a specific text area named "emri", using the document.onload but without success. Some would say to use it as a script or smth, but i want to use it as an attribute inside the tag. What am i doing wrong?

```<code> <!doctype html>
  <html lang="en">

  <head>
     <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1,
  shrink-to-fit=no">

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
    crossorigin="anonymous">

<link rel="stylesheet" href="App.css">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ"
    crossorigin="anonymous">

   </head>

   <body onload="document.my-form1.emri.focus();" >

  <main class="my-form">
      <div class="container">
          <div class="row justify-content-flex-start">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">Apliko</div>
                    <div class="card-body">
                        <form name="my-form1" onsubmit=" return formValidation();">
                            <div class="form-group row">
                                <label for="emri" class="col-md-3 col-form-label text-md-right">Emri juaj:</label>
                                <div class="col-md-6">
                                    <input type="text"  class="form-control" name="emri">
                                </div>
                            </div>
</code>```

答:
You can just add the autofocus attribute to the input.

```<code><input type="text"  class="form-control" name="emri" autofocus>
</code>```

Title: How to use document.onload Properly

Body:
I am currently learning window.onload and document.onload as attributes on html. But i fail to use them properly. In my code i want to focus a specific text area named "emri", using the document.onload but without success. Some would say to use it as a script or smth, but i want to use it as an attribute inside the tag. What am i doing wrong?

 <!doctype html>

     <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1,
  shrink-to-fit=no">

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
    crossorigin="anonymous">

<link rel="stylesheet" href="App.css">

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ"
    crossorigin="anonymous">

Apliko

                        <form name="my-form1" onsubmit=" return formValidation();">

                                Emri juaj:

                                    <input type="text"  class="form-control" name="emri">

Body:
You can just add the autofocus attribute to the input.

<input type="text"  class="form-control" name="emri" autofocus>


问:
Replace view if no ads is shown - AdMob
I've an application which uses AdMob as advertisement. And every time no ads is shown it's just a "view" with nothing inside it. I am now looking to replace the empty space and add an image. Is this possible?

So, how can I replace my "view" if no ads is shown, and add an image inside it?

I've tried to googling around, but could not find anything about this.

```<code>//Request Advertisement
let request = GADRequest()
request.testDevices = [kGADSimulatorID]

//Set up advertisement
advertisementBanner.adUnitID = "ca-app-pub-7225493999040026/4779408290"

advertisementBanner.rootViewController = self
advertisementBanner.delegate = self
advertisementBanner.load(request)
</code>```

The current result is: If no ads is available there will be just an empty space in the view. I wanna replace this empty space with an image.

答:
Use GADBannerViewDelegate to do this

```<code>func adViewDidReceiveAd(_ bannerView: GADBannerView) {
    print("adViewDidReceiveAd")
}

func adView(_ bannerView: GADBannerView,
            didFailToReceiveAdWithError error: GADRequestError) {
    print("adView:didFailToReceiveAdWithError: \(error.localizedDescription)")
    cnstAddViewHeight.constant = 0.0 // you can hide your view or replace with image here
}
</code>```

Title: Replace view if no ads is shown - AdMob

Body:
I've an application which uses AdMob as advertisement. And every time no ads is shown it's just a "view" with nothing inside it. I am now looking to replace the empty space and add an image. Is this possible?

So, how can I replace my "view" if no ads is shown, and add an image inside it?

I've tried to googling around, but could not find anything about this.

//Request Advertisement
let request = GADRequest()
request.testDevices = [kGADSimulatorID]

//Set up advertisement
advertisementBanner.adUnitID = "ca-app-pub-7225493999040026/4779408290"

advertisementBanner.rootViewController = self
advertisementBanner.delegate = self
advertisementBanner.load(request)

The current result is: If no ads is available there will be just an empty space in the view. I wanna replace this empty space with an image.

Body:
Use GADBannerViewDelegate to do this

func adViewDidReceiveAd(_ bannerView: GADBannerView) {
    print("adViewDidReceiveAd")
}

func adView(_ bannerView: GADBannerView,
            didFailToReceiveAdWithError error: GADRequestError) {
    print("adView:didFailToReceiveAdWithError: \(error.localizedDescription)")
    cnstAddViewHeight.constant = 0.0 // you can hide your view or replace with image here
}


问:
Disable shortcuts in Google Chrome
Is there a way to disable and replace shortcut commands in Google Chrome. I want to use Chrome for a public computer that only can access one site. Because of this I want to disable keys like Ctrl+Tab, Ctrl+T, Alt+F4 and I want to change F11 to a command like Ctrl+Shift+Alt+J (example) to stop users from exiting full screen mode.

Settings on the network block everything but a specific domain but now I want to block the user from exiting the browser.

答:
Chrome has Kiosk Mode, but that won't prevent users from using OS keyboard shortcuts (like ALT+F4, which aren't part of Chrome. Windows handles those). To start it in Kiosk Mode, run it using these parameters:

```<code>chrome.exe --kiosk http://www.google.com
</code>```

My public library actually did something pretty awesome: they installed an extremely minimal Debian build on their kiosks, and run Google Chrome on each one. There are no close buttons, and no desktop to get into, so this deters virtually all the CTRL+ALT+DELETE hackers out there. ALT+F4 doesn't work either, and closing the browser  by right-clicking opens up another one instantly.

But they forgot to get rid of GRUB's 10 second timeout, which lets users (well, me) get into recovery mode -_-, so I'm working with them to get that fixed...

I'd seriously consider Linux, as you can install it really quickly on multiple computers and basically forget about viruses and security. But the downside is that there isn't a "Administrator Panel" for you to tweak things with. You'd have to whip out nano (sorry, can't get used to vim) and edit some config files.

Title: Disable shortcuts in Google Chrome

Body:
Chrome has Kiosk Mode, but that won't prevent users from using OS keyboard shortcuts (like ALT+F4, which aren't part of Chrome. Windows handles those). To start it in Kiosk Mode, run it using these parameters:

chrome.exe --kiosk http://www.google.com

My public library actually did something pretty awesome: they installed an extremely minimal Debian build on their kiosks, and run Google Chrome on each one. There are no close buttons, and no desktop to get into, so this deters virtually all the CTRL+ALT+DELETE hackers out there. ALT+F4 doesn't work either, and closing the browser  by right-clicking opens up another one instantly.

But they forgot to get rid of GRUB's 10 second timeout, which lets users (well, me) get into recovery mode -_-, so I'm working with them to get that fixed...

I'd seriously consider Linux, as you can install it really quickly on multiple computers and basically forget about viruses and security. But the downside is that there isn't a "Administrator Panel" for you to tweak things with. You'd have to whip out nano (sorry, can't get used to vim) and edit some config files.


问:
How do I ensure fast and reliable datasets migration to fiware backend?
Transferring a very large datasets to fiware backend: SourceDB ->Orion -> Cygnus -> Postgres. For this I write a python script fetching rows and for each row fetched, send a payload to the Orion.

The script is firing at 150ms(0.15sec) intervals, but to my surprise after about 10 iterations, only two values (the first & last payloads sent) was persisted to the Postgres sink. Meaning 80% of the datasets aren't persisted to the sink.

Script:

```<code>import psycopg2
from time import sleep
from config import config
from tqdm import tqdm
import requests
import json

def val_json():
    db = "select to_json(d) from (  select \
        n.noise_data as measurand, \
        n.factor as \"sonometerClass\", \
        to_timestamp(n.seconds) as \"dateObserved\", \
        l.description as name, \
            json_build_object( \
                'coordinates', \
                json_build_array(l.node_lon, l.node_lat) \
            ) as location \
        from noise as n \
            inner join deployment as d on \
                d.deployment_id = n.deployment_id \
            inner join location as l on \
                l.location_id = d.location_id \
        order by n.seconds asc \
    ) as d"
    return db

def main():

    url = 'http://localhost:1026/v2/entities/002/attrs?options=keyValues'
    headers = {"Content-Type": "application/json", \
               "fiware-service": "urbansense",  \
               "fiware-servicepath": "/basic"}

    conn = None
    try:
        params = config()
        with psycopg2.connect(**params) as conn:
            with conn.cursor(name='my_cursor') as cur:
                cur.itersize = 5000
                cur.execute(val_json())

                for row in tqdm(cur):
                    jsonData = json.dumps(row)
                    if jsonData.startswith('[') and jsonData.endswith(']'):
                        jsonData = jsonData[1:-1]
                        print()
                        print(jsonData)
                    requests.post(url, data= jsonData, headers=headers)
                    sleep(0.15)

                cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()

if __name__ == '__main__':
    main()
</code>```

First ten iterations (payloads):

```<code>$python3 noiselevelObserved.py
0it [00:00, ?it/s]
{"measurand": 64.8, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:15+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
1it [00:00,  1.75it/s]
{"measurand": 58.8, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:16+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
2it [00:00,  2.23it/s]
{"measurand": 56.5, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:17+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
3it [00:00,  2.76it/s]
{"measurand": 61.1, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}
4it [00:01,  3.31it/s]
{"measurand": 108.5, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Pr. Liberdade Cardosas", "location": {"coordinates": [-8.611119, 41.146023]}}
5it [00:01,  3.86it/s]
{"measurand": 56.5, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
6it [00:01,  4.35it/s]
{"measurand": 59.9, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}
7it [00:01,  4.78it/s]
{"measurand": 97.2, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "D. Manuel II", "location": {"coordinates": [-8.625192, 41.148558]}}
8it [00:01,  5.12it/s]
{"measurand": 108.6, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Pr. Liberdade Cardosas", "location": {"coordinates": [-8.611119, 41.146023]}}
9it [00:01,  5.41it/s]
{"measurand": 57.1, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
10it [00:02,  5.63it/s]
{"measurand": 53.9, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:20+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}
</code>```

Reading attributes' values persisted into postgres:

```<code>postgres=# select  * from urbansense.basic_002_noiselevelobserved ;
  recvtimets   |         recvtime         | fiwareservicepath | entityid |     entitytype     |    attrname    |    attrtype     |               attrvalue               | attrmd
---------------+--------------------------+-------------------+----------+--------------------+----------------+-----------------+---------------------------------------+--------
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:15+01:00             | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 64.8                                  | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 1                                     | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:20+01:00             | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.63041,41.158091]}  | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 53.9                                  | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Casa da Musica                        | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
(14 rows)
</code>```

Changing the firing rate to 1-second interval doesn't give much improvement, only the 3 result sets (payloads) were persisted (70% lost):

```<code>postgres=# select  * from urbansense.basic_002_noiselevelobserved ;
  recvtimets   |         recvtime         | fiwareservicepath | entityid |     entitytype     |    attrname    |    attrtype     |               attrvalue               | attrmd
---------------+--------------------------+-------------------+----------+--------------------+----------------+-----------------+---------------------------------------+--------
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:15+01:00             | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 64.8                                  | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 1                                     | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:18+01:00             | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 56.5                                  | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:20+01:00             | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.63041,41.158091]}  | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 53.9                                  | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Casa da Musica                        | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
(21 rows)
</code>```

I honestly wouldn't like the firing rate to be up to a second because of the data size to be migrated to continue my research. When I first tried it at 1-second interval, I realised is going to take months to complete (maybe 4).

Question: Is Orion CB (or maybe Cygnus) not built to have such power of receiving entity/attributes values at such a rate (150ms/0.15s), Or maybe Cygnus isn't smart enough to receive notification from Orion at such a rate?.

I will appreciate any suggestion to ensure all values are persisted in the shortest time.

答: Based on the discussion in the question comments, the solution to this was to remove the throttling parameter in the subscription. It makes sense: the throttling makes some notification not being sent (in this particular case, 80% of all the notifications).

Body:
Transferring a very large datasets to fiware backend: SourceDB ->Orion -> Cygnus -> Postgres. For this I write a python script fetching rows and for each row fetched, send a payload to the Orion.

The script is firing at 150ms(0.15sec) intervals, but to my surprise after about 10 iterations, only two values (the first & last payloads sent) was persisted to the Postgres sink. Meaning 80% of the datasets aren't persisted to the sink.

Script:

import psycopg2
from time import sleep
from config import config
from tqdm import tqdm
import requests
import json

def val_json():
    db = "select to_json(d) from (  select \
        n.noise_data as measurand, \
        n.factor as \"sonometerClass\", \
        to_timestamp(n.seconds) as \"dateObserved\", \
        l.description as name, \
            json_build_object( \
                'coordinates', \
                json_build_array(l.node_lon, l.node_lat) \
            ) as location \
        from noise as n \
            inner join deployment as d on \
                d.deployment_id = n.deployment_id \
            inner join location as l on \
                l.location_id = d.location_id \
        order by n.seconds asc \
    ) as d"
    return db

def main():

    url = 'http://localhost:1026/v2/entities/002/attrs?options=keyValues'
    headers = {"Content-Type": "application/json", \
               "fiware-service": "urbansense",  \
               "fiware-servicepath": "/basic"}

    conn = None
    try:
        params = config()
        with psycopg2.connect(**params) as conn:
            with conn.cursor(name='my_cursor') as cur:
                cur.itersize = 5000
                cur.execute(val_json())

                for row in tqdm(cur):
                    jsonData = json.dumps(row)
                    if jsonData.startswith('[') and jsonData.endswith(']'):
                        jsonData = jsonData[1:-1]
                        print()
                        print(jsonData)
                    requests.post(url, data= jsonData, headers=headers)
                    sleep(0.15)

                cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()

if __name__ == '__main__':
    main()

First ten iterations (payloads):

$python3 noiselevelObserved.py
0it [00:00, ?it/s]
{"measurand": 64.8, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:15+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
1it [00:00,  1.75it/s]
{"measurand": 58.8, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:16+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
2it [00:00,  2.23it/s]
{"measurand": 56.5, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:17+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
3it [00:00,  2.76it/s]
{"measurand": 61.1, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}
4it [00:01,  3.31it/s]
{"measurand": 108.5, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Pr. Liberdade Cardosas", "location": {"coordinates": [-8.611119, 41.146023]}}
5it [00:01,  3.86it/s]
{"measurand": 56.5, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:18+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
6it [00:01,  4.35it/s]
{"measurand": 59.9, "sonometerClass": 1, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}
7it [00:01,  4.78it/s]
{"measurand": 97.2, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "D. Manuel II", "location": {"coordinates": [-8.625192, 41.148558]}}
8it [00:01,  5.12it/s]
{"measurand": 108.6, "sonometerClass": 2, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Pr. Liberdade Cardosas", "location": {"coordinates": [-8.611119, 41.146023]}}
9it [00:01,  5.41it/s]
{"measurand": 57.1, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:19+01:00", "name": "Trindade", "location": {"coordinates": [-8.609973, 41.151943]}}
10it [00:02,  5.63it/s]
{"measurand": 53.9, "sonometerClass": 0, "dateObserved": "1970-01-01T01:00:20+01:00", "name": "Casa da Musica", "location": {"coordinates": [-8.63041, 41.158091]}}

Reading attributes' values persisted into postgres:

postgres=# select  * from urbansense.basic_002_noiselevelobserved ;
  recvtimets   |         recvtime         | fiwareservicepath | entityid |     entitytype     |    attrname    |    attrtype     |               attrvalue               | attrmd
---------------+--------------------------+-------------------+----------+--------------------+----------------+-----------------+---------------------------------------+--------
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:15+01:00             | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 64.8                                  | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559045918129 | 2019-05-28T12:18:38.129Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 1                                     | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:20+01:00             | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.63041,41.158091]}  | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 53.9                                  | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Casa da Musica                        | []
 1559045919723 | 2019-05-28T12:18:39.723Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
(14 rows)

Changing the firing rate to 1-second interval doesn't give much improvement, only the 3 result sets (payloads) were persisted (70% lost):

postgres=# select  * from urbansense.basic_002_noiselevelobserved ;
  recvtimets   |         recvtime         | fiwareservicepath | entityid |     entitytype     |    attrname    |    attrtype     |               attrvalue               | attrmd
---------------+--------------------------+-------------------+----------+--------------------+----------------+-----------------+---------------------------------------+--------
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:15+01:00             | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 64.8                                  | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559046840569 | 2019-05-28T12:34:00.569Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 1                                     | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:18+01:00             | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.609973,41.151943]} | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 56.5                                  | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Trindade                              | []
 1559046845620 | 2019-05-28T12:34:05.620Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | dateObserved   | Text            | 1970-01-01T01:00:20+01:00             | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | latitude       | Number          | 41.1591                               | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | location       | StructuredValue | {"coordinates":[-8.63041,41.158091]}  | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | longitude      | Number          | -8.65915                              | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | measurand      | Number          | 53.9                                  | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | name           | Text            | Casa da Musica                        | []
 1559046850679 | 2019-05-28T12:34:10.679Z | /basic            | 002      | NoiseLevelObserved | sonometerClass | Number          | 0                                     | []
(21 rows)

I honestly wouldn't like the firing rate to be up to a second because of the data size to be migrated to continue my research. When I first tried it at 1-second interval, I realised is going to take months to complete (maybe 4).

Question: Is Orion CB (or maybe Cygnus) not built to have such power of receiving entity/attributes values at such a rate (150ms/0.15s), Or maybe Cygnus isn't smart enough to receive notification from Orion at such a rate?.

I will appreciate any suggestion to ensure all values are persisted in the shortest time.