<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sam J</title>
    <description>The latest articles on Forem by Sam J (@samj).</description>
    <link>https://forem.com/samj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F401366%2F7cc8ceb9-2e88-40f0-8837-7697b157a99a.png</url>
      <title>Forem: Sam J</title>
      <link>https://forem.com/samj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/samj"/>
    <language>en</language>
    <item>
      <title>HarperDB’s New Upsert Feature</title>
      <dc:creator>Sam J</dc:creator>
      <pubDate>Mon, 14 Dec 2020 18:06:01 +0000</pubDate>
      <link>https://forem.com/harperfast/harperdb-s-new-upsert-feature-l5l</link>
      <guid>https://forem.com/harperfast/harperdb-s-new-upsert-feature-l5l</guid>
      <description>&lt;p&gt;In our new &lt;a href="https://harperdb.io/developers/release-notes/" rel="noopener noreferrer"&gt;2.3.0 release&lt;/a&gt;, we included an often requested NoSQL upsert operation to HarperDB*.  This new hybrid operation will insert new records, if they do not exist, or update them, if they do.&lt;/p&gt;

&lt;p&gt;This new feature can be used in two different ways via HarperDB’s API - via a simple NoSQL &lt;code&gt;operation&lt;/code&gt; or as the &lt;code&gt;action&lt;/code&gt; for a bulk load operation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*This new operation is only available in HDB instances utilizing a LMDB data store. While the File System (FS) data store is still configurable and are still supported in HDB, some new/more advanced features may not be implemented for FS moving forward.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  NoSQL Upsert Operation
&lt;/h2&gt;

&lt;p&gt;As noted above, HarperDB users can now utilize an upsert operation via our API which will insert new records and/or update existing records.  &lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;new record&lt;/strong&gt; (to be inserted) is identified as a record that does not include a hash value or with a hash value that does not already exist on the table being upserted to.  &lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;existing record&lt;/strong&gt; (to be updated) is identified by a valid table hash value and will be updated based on the attribute values included in the JSON to upsert for that record - &lt;em&gt;i.e. as with update, any attributes not included in the record’s JSON will NOT be updated.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example NoSQL Upsert Operation
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Example Request&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upsert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"table"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"records"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;            
                &lt;/span&gt;&lt;span class="nl"&gt;"nickname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sammy"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Harper"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"nickname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Good boy!"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"breed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mutt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"weight_lbs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;155&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example Response&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upserted 2 of 2 records"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"upserted_hashes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"6bca9762-ad06-40bd-8ac8-299c920d0aad"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In the above example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The existing record with hash value equal to &lt;code&gt;1&lt;/code&gt;, will have the nickname attribute updated to equal “Sammy” and all other attribute values for that record will remain untouched. 
&lt;em&gt;Note: if there was no record with &lt;code&gt;id&lt;/code&gt; equal to &lt;code&gt;1&lt;/code&gt;, a new record would be inserted with the provided nickname value.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The new record will be inserted as written and with a system generated hash value.  &lt;em&gt;If a new, unused hash value had been provided for this record, we would have used that hash value when inserting the new record.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  NoSQL Bulk Load Upsert
&lt;/h2&gt;

&lt;p&gt;Similar to our NoSQL &lt;code&gt;insert&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; operations, &lt;code&gt;upsert&lt;/code&gt; is also now available to specify as the &lt;code&gt;action&lt;/code&gt; on a bulk load API operation. This will communicate to the bulk load job to run an upsert operation on the large data set provided.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bulk Load w/ Upsert Action
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Request&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"operation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"csv_url_load"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upsert"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"table"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"dogs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"csv_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"https://s3.amazonaws.com/data/dogs.csv"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Response&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Starting job with id e047424c-5518-402f-9bd4-998535b65336"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example Response from &lt;code&gt;get_job&lt;/code&gt; operation for bulk load&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"__createdtime__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1607897781553&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"__updatedtime__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1607897784027&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"created_datetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1607897781549&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"end_datetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1607897784026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e047424c-5518-402f-9bd4-998535b65336"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"job_body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"successfully loaded 348 of 348 records"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"start_datetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1607897781562&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COMPLETE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"csv_url_load"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"start_datetime_converted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-12-13T22:16:21.562Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"end_datetime_converted"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2020-12-13T22:16:24.026Z"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In the above example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;csv_url_load&lt;/code&gt; bulk load operation is started using the linked data set.  All records included in the linked data will be upserted into the table identified using the logic described above.&lt;/li&gt;
&lt;li&gt;Hitting the &lt;code&gt;get_job&lt;/code&gt; endpoint with the job id will provide you with an updated status of the bulk load job and, when complete, confirm the number or records upserted from the linked data set.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Note RE: Clustering
&lt;/h2&gt;

&lt;p&gt;As with other database operations like &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;csv_file_load&lt;/code&gt;, etc., in HarperDB, an &lt;code&gt;upsert&lt;/code&gt; operation to a table on a specific node will distribute to the other nodes subscribed to changes on that table.  &lt;/p&gt;

&lt;p&gt;A few things to keep in mind when thinking through how this will play out for your clustering architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In a scenario where you are upserting new records without hash values provided, the system generated hashes will be included in the transaction payload that is shipped to connected nodes - &lt;em&gt;i.e. the auto-generated hashes for the new records will be mirrored on connected nodes.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In a clustered architecture, it is important to take a moment to consider the best NoSQL operation to use in every situation, while it may seem easy to just use upsert even when you are only intending to insert or update those records, there could be unintended consequences to your data integrity from that strategy.&lt;br&gt;&lt;br&gt;
For example, in a scenario where you have provided the hash values for upsert records, the upsert transaction will do one of the following on any connected nodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;If no matching hash value is found on the subscribing table, a new record will be inserted on the table even if the operation on the publishing node was an update on the record&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;If there is a hash value match on the subscribing table, the record will be updated even if the operation on the publishing node was a record insert&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;To be specific, in some scenarios, using upsert could cause hash values for what you consider to be the same record to become out of sync across the cluster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While this may not make a difference to the overall value or use of your data cluster - it could be the preferred outcome! - in others, your data cluster may be affected negatively so think through your use case carefully. Being explicit about the operation you want to transact will also make reviewing and understanding the &lt;a href="https://harperdb.io/developers/documentation/reference/transaction-log/" rel="noopener noreferrer"&gt;transaction logs&lt;/a&gt; on your clustered nodes easier in the case where an issue arises and a rollback/fix is needed.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Happy upserting!&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Do you have a new feature idea for HarperDB?&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Our &lt;a href="https://feedback.harperdb.io/" rel="noopener noreferrer"&gt;Feedback Board&lt;/a&gt; is a great place to vote and leave product suggestions, and you can always connect with our team in the community &lt;a href="https://join.slack.com/t/harperdbcommunity/shared_invite/zt-e8w6u1pu-2UFAXl_f4ZHo7F7DVkHIDA" rel="noopener noreferrer"&gt;Slack Channel&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>node</category>
      <category>nosql</category>
      <category>harperdb</category>
    </item>
    <item>
      <title>HarperDB's New Approach to Role Permissions</title>
      <dc:creator>Sam J</dc:creator>
      <pubDate>Thu, 27 Aug 2020 15:59:40 +0000</pubDate>
      <link>https://forem.com/harperfast/harperdb-s-new-approach-to-role-permission-27nd</link>
      <guid>https://forem.com/harperfast/harperdb-s-new-approach-to-role-permission-27nd</guid>
      <description>&lt;p&gt;In our 2.2.0 version release this week, we made major changes to the way role permissions are managed and used in HarperDB.  &lt;/p&gt;

&lt;p&gt;Prior to this release, we used permissions as a way to explicitly identify schema items to restrict role access to.  In our new release, we have flipped that paradigm and now use permissions as a way to explicitly identify schemas and tables to grant role access to.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are two important things to call out at a high-level about what these changes mean:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Any schema and/or table that does not have CRUD permissions explicitly defined for a role will not be accessible for that role.&lt;/li&gt;
&lt;li&gt;If a role does NOT have specific attribute permissions set on a table, all attribute permissions will mirror the tables.  If there are attribute permissions set, all other attributes will be fully locked down. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  More Details about HarperDB Role Permissions
&lt;/h2&gt;

&lt;p&gt;HarperDB utilizes a Role-Based Access Control (RBAC) framework to manage access to HarperDB instances.  A user is assigned a role that determines the user's permissions to access database resources and run core operations.&lt;/p&gt;

&lt;p&gt;Role permissions in HarperDB are broken into two categories - permissions around database manipulation and permissions around database definition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Manipulation&lt;/strong&gt;:  A role defines CRUD permissions against database resources (i.e. data) in a HarperDB instance. Roles not assigned super_user permissions will only have the schema CRUD access explicitly defined within their role’s permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Definition&lt;/strong&gt;:  Permissions related to managing schemas, tables, roles, users, and other system settings and operations are restricted to the built-in super_user role. &lt;/p&gt;

&lt;h2&gt;
  
  
  Built-In Roles
&lt;/h2&gt;

&lt;p&gt;There are two built-in roles within HarperDB. See full breakdown of operations restricted to only super_user roles &lt;a href="https://harperdbhelp.zendesk.com/hc/en-us/articles/360053414613" rel="noopener noreferrer"&gt;in our docs&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;super_user&lt;/strong&gt;&lt;/em&gt; - this role provides full access to all operations and methods within a HarperDB instance, this can be considered the admin role.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This role provides full access to all Database Definition operations and the ability to run Database Manipulation operations across the entire database schema with no restrictions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;cluster_user&lt;/strong&gt;&lt;/em&gt; - this role is an internal system role type that is used and managed internally to allow clustered instances to communicate with one another.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  User-Defined Roles
&lt;/h2&gt;

&lt;p&gt;In addition to the built-in roles above, admins (i.e. users assigned to the super_user role) can create customized roles for other users to interact with and manipulate the data within explicitly defined tables and attributes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Unless the user-defined role is given "super_user" permissions, permissions must be defined explicitly within the request body JSON.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Describe operations will return metadata for all schemas, tables, and attributes that a user-defined role has CRUD permissions for.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;More information and details about how to effectively create and manage role permissions in our new paradigm can be found &lt;a href="https://harperdbhelp.zendesk.com/hc/en-us/articles/360051486534" rel="noopener noreferrer"&gt;in our docs&lt;/a&gt;.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coming Over the Horizon
&lt;/h2&gt;

&lt;p&gt;We are always working to make improvements to the way HarperDB allows our users to easily and effectively create and manage their database instances.  One additional enhancement we are looking to implement for role permissions soon is to allow user-defined, non-super_user roles to be assigned access to specific database description and/or manipulation operations that are currently restricted to super_user roles. &lt;/p&gt;

&lt;p&gt;Allowing a more ad hoc approach to assigning permissions on an operation-specific level, in addition to the existing schema-level permissions, will enable administrators the ability to more  effectively customize roles for their individual use cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Do you have requests for HarperDB’s role permission functionality or another feature/functionality?  Be sure to post it on our &lt;a href="https://harperdb.featureupvote.com/" rel="noopener noreferrer"&gt;Feature Request board&lt;/a&gt;!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;HarperDB is a distributed database focused on making data management simple. It has an easy to use REST API and supports NoSQL and SQL (including joins). Sign up for free and have your new HarperDB instance up and running in minutes &lt;a href="https://studio.harperdb.io/sign-up?code=SamHDB" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>database</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Performance Testing Javascript &amp; Node with Benchmark.js</title>
      <dc:creator>Sam J</dc:creator>
      <pubDate>Wed, 03 Jun 2020 20:58:51 +0000</pubDate>
      <link>https://forem.com/harperfast/performance-testing-javascript-node-with-benchmark-js-4g1f</link>
      <guid>https://forem.com/harperfast/performance-testing-javascript-node-with-benchmark-js-4g1f</guid>
      <description>&lt;p&gt;At HarperDB, we’re working to build the best distributed database solution from the edge to the cloud. As a software developer on the team, I spend most of my time thinking about how to increase the stability and speed of our codebase – ideally, any work I’m doing achieves both of these priorities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Benchmark.js to Test Functions in Node
&lt;/h2&gt;

&lt;p&gt;The purpose of this post is to share one way I use &lt;a href="https://benchmarkjs.com" rel="noopener noreferrer"&gt;Benchmark.js&lt;/a&gt; as a framework for quickly testing the most performant way to complete an operation in our code.  In our upcoming release slated for late October, we spent a lot of time pulling out our file system code and putting it behind a data layer facade.  This allowed me many opportunities to look at more performant options for things both big and small.&lt;/p&gt;

&lt;p&gt;The example I’ve chosen to use below is a simple one I created when working through new ways to strip the .hdb file extension from the hash values we retrieve when searching for data in the file system.  You can learn more about how we use FS in our patented data model in my last blog post &lt;a href="https://www.harperdb.io/blog/building-an-edge-database-for-iot" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up a Benchmark Project
&lt;/h3&gt;

&lt;p&gt;In order to make this as easy as possible, I have a project saved locally that allows me to quickly setup a performance test. I’ve created a &lt;a href="https://github.com/sljohnsondev/performance_playground" rel="noopener noreferrer"&gt;sample repo on Github&lt;/a&gt; to give you an idea of what this looks like.&lt;/p&gt;

&lt;p&gt;When I’m looking to test a new way to complete an operation in the code I’m writing, I create a new directory with a performance-test and test-methods files  (or overwrite existing ones) in the  “performance-playground” project I have saved locally.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;In the &lt;code&gt;test-methods&lt;/code&gt; file, I write up the different functions I am looking to test with a descriptive function name.&lt;/strong&gt; Usually, I include the initial method as a reference point. If I’m working on refactoring only a small part of a larger function, I will break it out to ensure I’m only testing the specific operation I’m thinking about/working on.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmjyptk4o7z4d09qeeks8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmjyptk4o7z4d09qeeks8.png" alt="Alt Text" width="681" height="643"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Once that’s done, I build out the performance-test to run each of the methods I’m testing with the same data I’ve manually set directly in the module, or a larger data set I’ve built out in a loop like the &lt;code&gt;create_test_array&lt;/code&gt; method above.&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64r69zpu7pv1efxdt27f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F64r69zpu7pv1efxdt27f.png" alt="Alt Text" width="706" height="642"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Once I’ve got my test setup, I can run the performance test in my terminal with &lt;code&gt;npm test&lt;/code&gt; or by manually running the module in WebStorm.&lt;/strong&gt; I get the following results…&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffrw79kvfc3vrd3vij7qa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffrw79kvfc3vrd3vij7qa.png" alt="Alt Text" width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Evaluating the Benchmark Results
&lt;/h3&gt;

&lt;p&gt;The above test clearly shows that &lt;code&gt;slice()&lt;/code&gt; is the most performant way to remove the &lt;code&gt;.hdb&lt;/code&gt; file extension from a string. With a clear direction to go, I would normally start thinking about other aspects of the method I’m working on and whether are other ways to tune for performance, but in this instance, updating the method to use &lt;code&gt;map()&lt;/code&gt; and &lt;code&gt;slice()&lt;/code&gt; will provide a big performance improvement over the existing method.&lt;/p&gt;

&lt;p&gt;While this example is simple, I think it provides a clear, easy-to-use framework for quickly testing different theories around the most performant way to code an operation in JavaScript. There are numerous ways this can be built out to test more robust functions and also with asynchronous methods in Node – e.g. I’ve used this to test different ways of using the async methods in the FS module.&lt;/p&gt;

</description>
      <category>node</category>
      <category>testing</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
