Blog

Notes on setting up Lockr on Acquia Dev Desktop

Posted on: 2017-09-01 11:01:14

Have been playing around with Lockr on Drupal 7 and want to play around with it locally and so I fall back to Acquia Dev Desktop.

Just as a note, as of the writing of this blog post, Acquia Dev Desktop ships with an invalid openssl.cnf location, so you have to provide one.

I found this out when I started getting this message while trying to create a certificate locally:

RuntimeException: Could not create private key. in Lockr\SiteClient->createCert() (line 37 of /Users/nvahalik/tmp/lockr/src/Lockr/SiteClient.php).

Bummer. Anyway. The fix is simple. Just add the following to your settings.php or local.settings.php (if you're on a Mac):

putenv("OPENSSL_CONF=/private/etc/ssl/openssl.cnf");

And if you're using Lockr, make sure this patch is applied. The patch is needed due to this bug in PHP.

Once you've done that you should be ready to lock and roll!

Continue reading...

An open letter to Dries: What are our values?

Posted on: 2017-03-30 23:57:21

An open letter to Dries Buytaert in response to the happenings with Larry Garfield and the Drupal project's values.

Continue reading...

Yield, Generators, and Iterators in Node.js

Posted on: 2017-03-09 12:57:32

Although I love Drupal, lately some of my projects have had me delve into learning new technologies and Stacks. The one I've spent more time with lately is Node.js.

One reason for this is that I've actually known JavaScript longer than I've known PHP. I started doing JavaScript about 21 years ago... (that feels like a lifetime ago). Anyhoo, I digress.

I tried playing around with Koa last night and it seems really slick. However I was trying to map my mind around this whole yield thing as well as how yield and Generators work together with yield to fundamentally change the way Javascript works.

So it finally dawned on me last night after reading some great articles:

That given this code:

var b = function* () {
  yield 1;
  return 4;
}

let c = b();
console.log(c.next()) // { value: 1, done: false }
console.log(c.next()) // { value: 4, done: true }

That in a sense you could rewrite it as:

var a = function () { return 1; }
var b = function () { return 4; }

console.log(a()) // 1
console.log(b()) // 4

Whenever a yield is encountered, it sort-of slices up the function and returns control back to the caller. The next time .next() is called, the yield expression is resolved and execution picks up where it left off.

Just had to write some thoughts down so I could process them.

Continue reading...

Perceived value and my favorite mobile game

Posted on: 2017-02-13 09:53:02

A few weeks ago I started playing Hill Climb Racing 2. It's a fun, addictive game and, best of all, it's free to play. You actually don't have to spend any money (though you do have to watch ads) but if you're patient, you can unlock everything without paying a single penny!

Recently, I figured I'd splurge and pay $4.99 for one of their little "deals" in the game where you get a deal with a custom decal and a heaping helping of these little things called Gems aka 💎.

Now, in the game, you buy vehicle upgrades with coins. You earn coins while driving, doing tricks, going longer and longer distances in the adventure levels, and winning cup races. You also earn 2-5 💎 every 6 hours through a "free reward" treasure box and a few more every day or two as you win 10 races by completing and winning cups. Anyway, over the course of a few weeks, you could potentially save a hundred or more gems.

Now gems in the game can only be used for two things: opening treasure boxes (which you get when you win a cup) or purchasing coins. You can't actually purchase coins, but you can purchase gems, which, in turn, can be exchanged for coins.

Now, initially when I did my initial splurge, I opted to "buy" (er, maybe convert) 1000💎 into coins. I got 130,000 coin out of the deal. Not bad, I thought to myself. That's 130 coin for every 💎.

But then I got to thinking... what would I get if I spent more? Here's the available conversions in the game:

💎CoinsC/💎
10010,000100
20022,000110
50060,000120
1000130,000130
2000280,000140
5000750,000250

Now, I know what you're probably thinking right now... man.. I should really opt for that 5000💎 deal where you can get 250C/💎, right? I mean that really is the better deal!

Well, a few moments ago remember I mentioned that you can use 💎 for 2 things. One is for buying coins, and the other is for unlocking treasure chests. Well, what happens if you only spent your 💎 unlocking treasure chests? Well...

💎CoinsC/💎
127,000375
2413,000~540
48??
9670,000~730

So with a little patience, it's actually a much better deal to unlock the chests. Sure, it can feel good to get "the best deal" but is it really the best deal? Not really...

Continue reading...

Acquia's Access Log File Format

Posted on: 2016-11-18 22:37:06

I needed to parse some logs and I wanted to know what Acquia's Log file format was. Here it is:

LogFormat "%{X-AH-Client-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\"
\"%{User-agent}i\" vhost=%v host=%{Host}i hosting_site= pid=%P
request_time=%D forwarded_for=\"%{X-Forwarded-For}i\"
request_id=\"%{X-Request-Id}i\" "`

Here's a link to the LogFormat reference.

Key tidbits:

request_time is in microseconds. Not milliseconds. So divide that sucker by 1,000,000.

Also, request_id will correlate requests across different log files (e.g. drupal-watchdog-<date> and/or drupal-requests-<date>.

Continue reading...

Building Kick SaaS Installation Profiles

Posted on: 2016-09-16 20:36:21

So back in April of this year, I gave a talk at Texas Camp entitled Building Kick SaaS Installation Profiles.

The slides are over there, but I'm uploading a local copy of them here—just in case!

Note: no audio is available, but the slides might be pretty handy!

Continue reading...

How to monitor any text file import

Posted on: 2016-07-08 15:18:51

So as I was sitting here just now waiting for an 80+ MB import to process over an SSH connection, I began wondering to myself if there was some way to monitor the progress of an import. Percentage—or even throughput—of the file being sent over the pipe.

Turns out that there is a way!

Enter the command pv.

pv allows a user to see the progress of data through a pipeline, by giving information such as time elapsed, percentage completed (with progress bar), current throughput rate, total data transferred, and ETA.

Uh. Yes, please.

If you're running GNU/Linux, you probably already have this installed. On a Mac it's available via Homebrew.

brew install pv

Once installed, you use it to send your text files to commands that are expecting things through stdin like so:

$ pv some-db.sql | mysql -uroot 8f00b204e9800998ecf8427e
83.2MiB 0:00:25 [3.28MiB/s] [==================================================================>] 100%

Never worry about where your imports are again!

Continue reading...

Taking a look at output buffering in PHP

Posted on: 2016-06-26 23:19:43

Output buffering in PHP isn't new. It was introduced in PHP 4 and for the most part, it's one of those things that unless you're not using a CMS or a framework, you'll never really need to mess with it much.

However, today I was playing around with doing client-side redirections in JavaScript and wanted to see first-hand how they worked. Modern browsers begin parsing the HTML before it is completely delivered and once the <script> tag is parsed, it is executed immediately.

So if we have a <script> tag just inside of our <head>, then that script tag will get executed as soon as it is done, regardless of the rest of the content in the delivered HTML file.

Anyway, to play around with this, I used this little bit of code:

<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\">
<html>
  <head>
    <title>Redirect test</title>
  </head>
  <body>
    <script>location.href=\"https://google.com/\"</script>
    <?php
      flush();
      sleep(10);
    ?>
  </body>
</html>

However, it did not work as intended.

I tried several different things trying to get it to work, but it wasn't until I added echo str_pad('', 64 * 1024).\"\\n\"; before the sleep that it actually worked:

<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\">
<html>
  <head>
    <title></title>
  </head>
  <body>
    <script>location.href=\"https://google.com/\"</script>
    <?php
      echo str_pad('', 64 * 1024).\"\\n\";
      sleep(10);
    ?>
  </body>
</html>

So, why did it need another 64k worth of stuff in order to have the intended effect? Well, the answer, of course, is buffering!

Yet another buffer!

I'm using Acquia DevDesktop for local development. It uses PHP's standard buffer size of 4096. No big deal there. I trying backing down the str_pad() to that and it still wouldn't send the data.

Ultimately, what I discovered was that FastCGI has a FcgidOutputBufferSize directive and it's value is actually set to—get this—65536.

So ultimately what was happening was that PHP's buffer was getting sent, but only to the handler (that'd be FastCGI) and then FastCGI was buffering the output itself.

It's also worth noting that using mod_deflate has it's own internal buffer (set by the DeflateBufferSize directive). I had it disabled for my test—and I'm not 100% sure of the impact that it might have.

One other quick note about flush(): As far as I can tell, each buffer will capture data until it gets full. Once it gets full, it will send it's data on to the next buffer. Say for a moment you have a sleep() call in your code that suspends execution. How long will it take for a the first byte to get delivered?

Buffer 6K 11K 16K
PHP, 4K 2K 3K 0
FastCGI, 8K 4K 8K 8K
Sent to browser 0 0 8K

In other words, the first buffer (PHP's) fills up and then sends it's data over to the next buffer (FastCGI's). FastCGI won't send it's buffer to the user until PHP delivers enough content to fill up it's own buffer so that it needs to empty it's buffer to start filling it up again.

It's something to keep in mind. And again, if Apache or something else is doing extra caching, you'll need to ensure you either bypass those buffers or send enough data so that buffers get flushed.

Continue reading...

Initial impression of the Hamshield

Posted on: 2016-05-23 09:12:32

Background and Intro

The Hamshield was a Kickstarter that ended sometime last summer. The original expected delivery date was October of 2015, but due to issues with manufacturing and a problem with their amplification circuits, it was delayed. I won't go into the details here, but you can read it on their Kickstarter page:

<iframe width=\"640\" height=\"360\" src=\"https://www.kickstarter.com/projects/749835103/hamshield-for-arduino-vhf-uhf-transceiver/widget/video.html\" frameborder=\"0\" scrolling=\"no\"> </iframe>

They started shipping about 3-4 weeks ago.

I got my Hamshield about 2 weeks ago. I was wanting to do more with it once I got it, but we're in the process of moving (and since it required some assembly & soldering) it had to wait until I could bust out the old soldering iron before I could do anything with it. Anyway, here are my thoughts and initial impression.

Assembly

Soldering on the headers wasn't bad at all. Once I got started, it took about 5 minutes to work through them. The GND pins by VIN didn't seem to want to solder very well at all. But everything else went very quickly.

The GND pins needed more love

The SMA connector was a bit much for my little 15 watt iron. Of course, all I had was a fine-tip on my iron, so a bigger tip would work much better on the SMA. My suggestion is to get the two pins on the back first, since they are smaller and tinned and tacked down much more easily than the pins on the tip of the board. I've got a 20W iron somewhere and I'll probably resolder this once I find it and put a bigger tip on it.

The only other "gripe" I had about the SMA jack (and this is really just due to my lack of a good tool) is that there are components really close to the jack. I'm talking about C19 and R9, specifically. It was tough to get the iron good and close to the pins. Take a look:

SMA pins did not solder well and there were components very close to them

The only other real thing that bothered me was the proximity of the headers near the USB port on the Uno:

Close-up of the header pins and the USB jack on the Uno

I stuck a piece of electrical tape on there just to be safe. It looks a little close for comfort.

Oh, and one other note. My shield didn't come with pass-thru headers... like most shield would have so that you could stack them. Not sure if that was a mistake or not, but it would be nice.

Using the Examples

The folks over at Enhanced Radio Devices provide an Arduino library on Github so that you can use and build stuff with your new shield.

Out of the box, I couldn't get the libraries to compile. I've submitted a pull-request to fix the issue, which appears to just be a pre-processor define that uses a hyphen in the name.

Once that was fixed, I was able to get the FMBeacon example loaded and going on the device. The audio was a bit anemic, but it does work:

<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/6DUnz-QK69Q\" frameborder=\"0\" allowfullscreen></iframe>

However, many of the other examples did not compile, JustTransmit does not work and some of the other ones do not work on Uno due to memory constraints.

There is also a reference in some of the applications to a PCM.h. There doesn't appear to be any documentation of what that is, specifically, but there are some PCM libraries for Arduino. So perhaps those would work.

Review

Well, I'm still excited about using the Hamshield. Though, it still seems like there is much to be cleaned up in the Arduino library and example applications. It'd be nice to be able to test things a bit better and I'm regretting not getting some sort of case for it since a 5W transmitter within a couple of feet will cause the unit to reboot. (I was trying to test the RSSI readings and it would just reboot while I tried this using a Baofeng HT).

Personally, I'd recommend getting some SMA pigtails and using that instead of the supplied antenna, but it will work in a pinch. It's hard to handle this thing with the antenna fully extended.

That's all for now. Thanks Casey and the folks at ERD for their efforts—looking forward to using it in my first real project!

Continue reading...

Importing a price in Drupal 8 for Drupal Commerce 2.x

Posted on: 2016-04-20 14:21:04

Just a quick note that if you're importing a Commerce price:

  • you must set the currency_code.

  • what was commerce_price in DC 1.x / Drupal 7 is now just price.

  • the number can be a decimal now.

    'price/number': SomeFieldName 'price/currency_code': plugin: default_value default_value: 'USD'

Note that you can also set up a constant in the migration definition and use the constant value:

source:
  plugin: d6_ubercart_product_variation
  constants:
    currency: USD
...
process:
  'price/number': SomeFieldName
  'price/currency_code': 'constants/currency'

It is worth mentioning that this fails silently right now. That is, if you don't provide the currency code, the migration will continue but you just won't have a value.

Update 2017-11-20: Vimokkhadipa told me that price/amount in the example above should actually be price/number. Since I haven't done any migration work in a while I'm taking his word for it and noting the update. Thanks Vimokkhadipa!

Continue reading...