use Mojolicious::Lite; use Fcntl qw(:flock); use Try::Tiny; use utf8; use feature qw( unicode_strings ); use autodie; use constant FILENAME => 'complaint_file.txt'; app->secret('UNUSED'); helper register_complaint => sub { my $self = shift; my $new_post = $self->param('new_complaint'); $new_post =~ s/^%%ENTRY%%\n//gsmx; # Minor sanitization. try { open my $of, '>>:encoding(UTF-8)', FILENAME; # Append flock $of, LOCK_EX; # Exclusive print {$of} "%%ENTRY%%\n$new_post\n"; flock $of, LOCK_UN; close $of; } catch { $self->app->log->warn($_); }; }; helper list_complaints => sub { my $self = shift; my @posts; try { open my $if, '<:encoding(UTF-8)', FILENAME; # Input local $/ = undef; flock $if, LOCK_SH; # Shared my $post = <$if>; flock $if, LOCK_UN; close $if; @posts = split /^%%ENTRY%%\n/gsmx, $post; shift @posts; } catch { $self->app->log->warn($_); }; chomp @posts; $self->stash(complaints => \@posts); }; any q{/} => sub { my $self = shift; $self->register_complaint if length $self->param('new_complaint'); $self->list_complaints; $self->render('index'); }; app->start; __DATA__ @@ index.html.ep % title 'Complaint Department'; <%= title %> % title 'Complaint Department'; %= form_for '/' => ( method => 'post' ) => begin

Please enter your complaint.

%= text_field 'new_complaint' %= end %== @{ stash('complaints' ) } ? '

Past complaints:

' : '';